繁体   English   中英

使用 AWK 选择输入记录字段

[英]Picking input record fields with AWK

假设我们有一个 shell 变量$x包含一个空格分隔的从 1 到 30 的数字列表:

$ x=$(for i in {1..30}; do echo -n "$i "; done)
$ echo $x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

我们可以使用 AWK 打印前三个输入记录字段,如下所示:

$ echo $x | awk '{print $1 " " $2 " " $3}'
1 2 3

我们如何使用 AWK 打印从第 N 个字段开始的所有字段? 例如

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

编辑:我可以使用 cut、sed 等来做同样的事情,但在这种情况下,我想知道如何使用 AWK 来做到这一点。

将我的评论转换为答案,以便将来的访问者轻松找到该解决方案。

您可以使用此awk

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

或通过 start position 作为参数:

awk -v n=3 '{for (i=n; i<=NF; ++i) printf "%s", $i (i<NF?OFS:ORS)}' file

版本 4:Shortest 可能是使用sub来切断前三个字段及其分隔符:

$ echo $x | awk 'sub(/^ *([^ ]+ +){3}/,"")'

Output:

4 5 6 7 8 9 ...

但是,这将保留$4之后的所有空间:

$ echo "1 2 3  4   5" | awk 'sub(/^ *([^ ]+ +){3}/,"")'
4   5

所以如果你想压缩空间,你需要,例如:

$ echo "1 2 3  4   5" | awk 'sub(/^ *([^ ]+ +){3}/,"") && $1=$1'
4 5

除了如果只有 4 个字段并且第 4字段恰好是 0:

$ echo "1 2 3 0" | awk 'sub(/^ *([^ ]+ +){3}/,"")&&$1=$1'
$ [no output]

在这种情况下,您需要:

$ echo "1 2 3 0" | awk 'sub(/^ *([^ ]+ +){3}/,"") && ($1=$1) || 1'
0

版本 1: cut更适合这份工作:

 $ cut -d\ -f 4- <<<$x

版本 2:使用 awk 您可以:

 $ echo -n $x | awk -v RS=\ -v ORS=\ 'NR>=4;END{printf "\n"}'

版本 3:如果您想保留这些不同数量的空间,使用 GNU awk 您可以使用split的第四个参数seps

 $ echo "1 2 3 4 5 6 7" | gawk '{ n=split($0,a,FS,seps) # actual separators goes to seps for(i=4;i<=n;i++) # loop from 4th printf "%s%s",a[i],(i==n?RS:seps[i]) # get fields from arrays }'

添加另一种方法将所有值添加到变量中,一旦所有字段值完成读取,只需打印变量的值。 根据您要从哪个字段开始获取数据来更改n=的值。

echo "$x" |
awk -v n=3 '{val="";for(i=n; i<=NF; i++){val=(val?val OFS:"")$i};print val}'

使用 GNU awk,您可以使用连接 function ,它自 gawk 4.1 以来一直是内置include

x=$(seq 30 | tr '\n' ' ')

echo "$x" | gawk '@include "join"   
                {split($0, arr)
                print join(arr, 4, length(arr), "|")}
                '
4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30

(为了清楚起见,这里用'|'而不是' '显示...)

包括join的替代方式:

echo "$x" | gawk -i join '{split($0, arr); print join(arr, 4, length(arr), "|")}'

使用 gnu awk 和 gensub:

echo $x | awk '{ print gensub(/^([[:digit:]]+[[:space:]]){3}(.*$)/,"\\2",$0)}'

使用 gensub,根据正则表达式将字符串分成两部分并仅打印第二部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM