修改以T开头的行:
$ awk '{sub(/^T.*/,"T|"NR)}1' file
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
D|849007|38|1208004|1
T|5
按照最初的要求修改输入文件的最后一行:
$ awk '{printf "%s",p} {p=$0 ORS} END{sub(/\|.*/,"|"NR,p); print p}' file
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
D|849007|38|1208004|1
T|5
由于在 cmets 中存在一些争论,为什么我对发布在 here 的 getline 解决方案投了反对票,并且因为很难在 cmets 中给出示例 - 这里有几个示例说明您为什么不应该使用 getline 解决方案(或任何类似的)这个问题(或任何类似的):
适用于一组输入:
$ cat file1
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
D|849007|28|1208004|1
T|3
$ awk '{printf "%s",p} {p=$0 ORS} END{sub(/\|.*/,"|"NR,p); print p}' file1
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
D|849007|28|1208004|1
T|5
$ awk '{l=$0; if(getline==1){print l; print} else {sub("\\|.*","|"NR);print}}' file1
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
D|849007|28|1208004|1
T|5
另一个失败:
$ cat file2
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
T|3
$ awk '{printf "%s",p} {p=$0 ORS} END{sub(/\|.*/,"|"NR,p); print p}' file2
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
T|4
$ awk '{l=$0; if(getline==1){print l; print} else {sub("\\|.*","|"NR);print}}' file2
H|ACCT|XEC|1|TEMP|20130215035845|
D|849002|48|1208004|1
D|849007|28|1208004|1
T|3
尴尬(充其量)以增强最小的工作,例如将每一行打印到 stderr 以进行调试:
$ awk '{print |"cat>&2"} {printf "%s",p} {p=$0 ORS} END{sub(/\|.*/,"|"NR,p); print p}' file2
$ awk '{print |"cat>&2"; l=$0; if(getline==1){print |"cat>&2"; print l; print} else {print |"cat>&2"; sub("\\|.*","|"NR); print}}' file1
请注意修改 2 个版本在简单性上的区别。修改getline 版本是笨拙的、复杂的、不平凡的、不明显的、低效的、容易出现潜在错误、需要重复代码和/或大量重写等...
我们在上面看到的是尝试使用getline 来解决 awk 的自然文本处理模式可以轻松处理的问题的非常常见的后果。
getline 在适当使用时很有用,请参阅http://awk.info/?tip/getline 了解一些有效应用程序的示例。