我正在写一个快速的awk脚本来转换这种格式的行:
AAAA BBBB CCCC DDDD...
至
CCCC AAAA BBBB DDDD...
这是我的脚本:
{ printf "%s %s %s %s", $3, $1, $2, $4 };
这个工作正常,除了当原始input行有超过4个标记,在这种情况下,第5个和以下的标记不打印。
我检查了一些答案,比如使用awk打印所有列从第n个到最后一个,但是他们依赖于将variables设置为""
,如果这些variables稍后被重用,这似乎会导致问题。
有没有一种简单的方法来取代$4
,如“从$ 4到行尾的子串”?
在这个简单的情况下,你所需要的是:
$ awk '{t=$3; $3=$2; $2=$1; $1=t}1' file CCCC AAAA BBBB DDDD
但一般用GNU awk for gensub()
, \s
和\S
:
$ awk '{print $3, $1, $2, gensub(/^\s*(\S+\s+){3}/,"","")}' file CCCC AAAA BBBB DDDD
gensub()
只是跳过前三个字段,并将从这一点离开所有字段和字段之间的空间:
$ cat file AAAA BBBB CCCC DDDD EEEE FFFF GGGG $ awk '{print $3, $1, $2, gensub(/^\s*(\S+\s+){3}/,"","")}' file CCCC AAAA BBBB DDDD EEEE FFFF GGGG
与其他awk你可以做match()+substr()
:
$ awk '{match($0,/^[[:space:]]*([^[:space:]]+[[:space:]]+){3}/); print $3, $1, $2, substr($0,RLENGTH+1)}' file CCCC AAAA BBBB DDDD EEEE FFFF GGGG
或者sub()
和一个变量:
$ awk '{x=$0; sub(/^[[:space:]]*([^[:space:]]+[[:space:]]+){3}/,"",x); print $3, $1, $2, x}' file CCCC AAAA BBBB DDDD EEEE FFFF GGGG
使用for
循环:
{ printf("%s %s %s", $3, $1, $2); for (i = 4; i <= NF; i++) printf("%s ", $i); printf("\n"); }
这并不一定“容易”,但并不那么难:
{ printf "%s %s %s ", $3, $1, $2; for (i=4; i<= NF; ++i) { printf "%s ", $i; } printf "\n"; }
另一种方法,有点聪明:
{ N3 = $3; N2 = $2; N1 = $1; // capture the fields $1 = N3; $2 = N1; $3 = N2; // reorder the fields print; // print the whole record }
Perl的:
perl -lane '($F[0], $F[2]) = ($F[2], $F[0]); print "@F"' file