awk 独立的 3 列

awk 独立的 3 列

我有一个如下所示的文件(各列由制表符分隔,并且可能包含空格):

    0637    apple    8528    1392    orange    1390    8528    unknown fruit    7537    1039    banana    1892    0989    pineapple    7537    8528    melon    7537    8528    grape    7537    8528    (null)    (null)

我需要将其分割为每 3 列,然后 grep 得到结果[0-9]$(我使用它awk是因为在大文件上比 grep 快得多):

0637    apple    8528
1392    orange    1390
8528    unknown fruit    7537
1039    banana    1892
0989    pineapple    7537
8528    melon    7537
8528    grape    7537

现在,我有这个美丽的执行此操作的命令:

awk -F\\t '{print $2 "\t" $3 "\t" $4 "\n" $5 "\t" $6 "\t" $7 "\n" $8 "\t" $9 "\t" $10 "\n" $11 "\t" $12 "\t" $13 "\n" $14 "\t" $15 "\t" $16 "\n" $17 "\t" $18 "\t" $19 "\n" $20 "\t" $21 "\t" $22 "\n" $23 "\t" $24 "\t" $25}' filename | awk '/[0-9]$/'

我还有一个丑陋的cut命令也有同样的作用。我仍在学习 awk,所以我相信有一种更明智的方法来做到这一点。另外,我可能如果超过的话就会遇到麻烦$25。你能帮助我吗?

答案1

这有效:

$ cat splitnum.awk
#!/bin/awk -f
BEGIN {
    FS = OFS = "\t"
}
{
    for ( i = 1; i < NF; i = i + 3) {
        if ( $(i+2) ~ /[0-9]+/ ) {
            print $i, $(i+1), $(i+2)
        }
    }
}
$ awk -f splitnum.awk filename

或者全部写在一行上:

awk 'BEGIN{FS=OFS="\t"}{for (i=1;i<NF;i=i+3){if ($(i+2) ~ /[0-9]+/) {print $i, $(i+1), $(i+2)}}}' filename

基本上循环遍历数据字段,一次三个,检查第三个字段是否由数字组成。

答案2

假设字段由一个或多个制表符分隔,并且每个字段可以包含空格但不能包含制表符,则以下内容应该有效

( IFS=$'\t'; printf '%s %s %s\n' $(<input_file) )

(子 shell 很方便,无需IFS为调用 shell 进行更改)。

或者,如果字段由一个或多个空格和制表符分隔,并且每个字段不包含空格或制表符,则以下内容应该有效

printf '%s %s %s\n' $(<input_file)

答案3

awk -F'\t' '{for(i=1;i<=NF;i++)if(!(i%3))$i=$i "\n"}1' file

答案4

对于 awk 讨厌者:

perl -pe 's/(\d+)\s+(\d+)/$1\n$2/g' | 
perl -lnpe 's/^\s*(\d+)\s+([^\d]+?)\s+(\d+).*/$1\t$2\t$3/' |
egrep '[0-9]$'

相关内容