我有一个看起来像这样的文件:
1 543423 34354
2 5654656 3423 xyz_1378,xyz_1379
3 4645656 34234354 xyz_1384,xyz_1385
4 5654 78678 xyz_1390,xyz_1391,xyz_1392
5 54654 76867 xyz_1411,xyz_1412,xyz_1413
6 54654 8678
7 56546 67867 xyz_1711
8 678 7867
9 76867 7876 xyz_2940
10 6786 678678 xyz_3101,xyz_3102,xyz_3103,xyz_3104,xyz_3105,xyz_3106,xyz_3107
11 67867 78678
注意它包含4个字段,空格分隔。最后一个(第四个)字段可能为空,并且可能包含以逗号分隔的多个值。
我想打印最后一行的所有值,每行一个。我怎么能这样做(最好用awk)?
更新: 我需要批量处理许多文件(获取所有文件的连接输出)。
这有效:
for x in *; do awk '{print $4}' $x/filename | awk --field-separator="," '{if ($0 != "") {for (i=1; i<NF+1; i++) print $i}}'; done;
并返回类似
的内容xyz_1378
xyz_1221
xyz_97
xyz_132523
xyz_242
我现在唯一缺少的是,我希望上面的每一行都以一个额外的字段开头 - $ x(来自for
循环的字段)。
我尝试将print $i
更改为print $x,$i" but
x`似乎在此范围内无法正确识别。有什么想法吗?
谢谢!
答案 0 :(得分:2)
使用awk的-v选项将变量传递给awk脚本,而不是依赖于shell的替换。此外,您只需要一次调用awk
for dir in *; do
awk -v "dir=$dir" '
NF==4 {
n = split($4, a, ",")
for (i=1; i<=n; i++) {print dir "\t" a[i]}
}
' "$dir/filename"
done
或者,如果你不介意看“dir / filename”:
awk '
NF==4 {
n = split($4, a, ",")
for (i=1; i<=n; i++) {print FILENAME "\t" a[i]}
}
' */filename
如果你有大量的目录,你的shell可能会在扩展“* / filename”时窒息,所以使用find和xargs:
find . -type f -name filename -print0 | xargs -0 awk '...'
(-print0 / -0选项需要GNU find / xargs)
答案 1 :(得分:0)
您可以将命令中的一个语句更改为
awk '{print FILENAME "," $4}' $x
然后处理此输出。
FILENAME
是用于获取正在处理的文件的文件名的内部awk变量。
答案 2 :(得分:-1)
使用NF>=4
作为条件,以查看字段中是否有任何内容。然后split($4,a,/,/)
将为您提供包含所有值的数组a
。把它放到一个大的结果数组中:
NF>=4 {
n = split($4, a, /,/);
for( i=1; i<=n; i++ ) {
result[a[i]] = 0;
}
}
并在最后打印:
END {
for( val in result ) {
print val;
}
}
如果您希望对其进行排序,请通过管道sort(1)