什么是Unix中用于交换字段的一行命令?

6

我有一个带有列表的文件

id1 str1 str2 .. strn
id2 str1 str2 .. strm

(str的数量可能会有所不同),我想要一个一行代码将其转换为

str1 str2 .. strn [id]
str1 str2 .. strm [id]

应该有一种使用awk的方法来实现这个,但我不知道如何在$1之后获取“所有字段”,特别是当它们的长度是可变的。

我的想法是类似于

cat file | awk '{ print $2 and the rest " [" $1 "]" }'

但只是缺少了"$2和其余内容"....


11个回答

3

使用 Perl

perl -F'\s+' -E 'say join " ", @F[1..$#F], "[" . @F[0] . "]"' file

输出

str1 str2 ... strn [id1]
str1 str2 ... strm [id2]

2

像这样:

awk '{v=$1;$1="";sub(/^ /, "");$NF=$NF" ["v"]"}1' file

或者为了可读性而分解成多行:

awk '{
    v=$1
    $1=""
    sub(/^ /, "")
    $NF=$NF" ["v"]"}
    1
' file

输出

str1 str2 ... strn [id1]
str1 str2 ... strm [id2]

解释

代码 注释
v=$1 将$1赋值给变量v
$1="" 取消设置$1
sub(/^ /, "") $0中删除前导空格
$NF=$NF" ["v"]" 将预期输出的ID作为变量v附加到最新字段$NF
1 print的简写形式

2
$ awk '{for(i=2;i<=NF;i++)printf "%s%s",$i,OFS (i==NF?"[" $1 "]" ORS:"")}' file

输出:

str1 str2 .. strn [id1]
str1 str2 .. strm [id2]

2
每个人都站起来,向前移动一个空间。
echo "a b c d e f" | awk '{ f=$1; for(i=1; i<NF; i++){ $i=$(i+1) }; $NF=f }1'

Output:

b c d e f a

2
$ awk '{$0=$0 " [" $1 "]"; sub(/^[^ ]+ /,"")} 1' file
str1 str2 .. strn [id1]
str1 str2 .. strm [id2]

或者如果您更喜欢:

$ awk '{for (i=2; i<=NF; i++) printf "%s ", $i; print "[" $1 "]"}' file
str1 str2 .. strn [id1]
str1 str2 .. strm [id2]

2

如果只处理第一个字段,那么基于正则表达式的解决方案似乎相当简单:

sed -E 's/([^[ ]+) (.*)/\2 [\1]/'

1

我会使用GNU AWK 来处理以下内容,假设有一个名为file.txt的文件,其内容如下:

id1 str1 str2 .. strn
id2 str1 str2 .. strm

那么

awk '{print substr($0,index($0," ")+1),"[" $1 "]"}' file.txt

输出结果

str1 str2 .. strn [id1]
str1 str2 .. strm [id2]
警告:我假设您的值由单个空格分隔,如果不是这种情况,请勿使用此解决方案。解释:我使用字符串函数通过查找第一个空格(通过index函数)来获取$2和其余内容,然后获取该空格后面的所有内容(通过substr函数),然后跟随着用[...]括起来的第一个字段值。

(在GNU Awk 5.0.1中测试)


1
另一个 的答案。
perl -lane '$f = shift @F; push @F, "[$f]"; print "@F"' file

0

使用 gnu awk 和一个带有 2 个捕获组的模式:

awk 'match($0, /^([^ ]+) +(.+)/, a) {print a[2], "["a[1]"]"}' file

或者使用 POSIX 括号表达式来匹配空格,例如 [[:space:]]

gawk 'match($0, /^([^[:space:]]+)[[:space:]]+(.+)/, a) {print a[2], "["a[1]"]"}' file

输出

str1 str2 .. strn [id1]
str1 str2 .. strm [id2]

0

这应该是一个一行代码的事情吧?

echo 'id1 str1 str2 .. strn
      id2 str1 str2 .. strm' | 
{m,g}awk '$!NF = substr($_, index($_, $(!_+!_))) " [" $!_ "]"'
str1 str2 .. strn [id1]
str1 str2 .. strm [id2]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接