我有一个如下所示的文件(各列由制表符分隔,并且可能包含空格):
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]$'