如何避免awk中system命令的输出写入目标文件?
解决awk中system命令输出被意外重定向的问题
首先得明确你遇到的问题根源:awk的system()函数执行外部命令时,该命令的标准输出会和awk自身的输出共用同一个stdout流。所以当你把整个awk命令的输出重定向到file_1时,wc -l file_1的输出(比如0 file_1)和awk里print "something"的内容会一起被写入目标文件。
另外这里还有个隐藏的逻辑误区:system()返回的是外部命令的退出状态码,而不是命令的输出结果。wc -l file_1只要文件存在,退出码永远是0,不管文件行数是多少。如果你实际是想判断file_1的行数是否为0,那原来的写法根本达不到目的,得先修正这个逻辑。
下面分两种场景给出解决方案:
场景1:仅需判断外部命令的执行状态(不关心命令输出)
如果你的需求确实是判断wc -l file_1是否成功执行(而非行数是否为0),只需把system()里的命令输出重定向到/dev/null,让它不占用awk的stdout:
awk 'BEGIN{ if ( system("wc -l file_1 > /dev/null") == 0 ) {print "something"} }' text.txt >> file_1
这样wc的输出会被丢弃,只有awk的print内容会追加到file_1里。
场景2:需要判断file_1的行数是否为0(修正原始逻辑)
如果你的真实需求是当file_1行数为0时输出"something",那用system()调用wc是低效且容易出错的方式,更优雅的做法是在awk内部捕获wc的输出,或者直接用awk统计行数:
方法A:用getline捕获wc的输出
awk 'BEGIN { # 用<重定向file_1给wc,避免wc输出文件名 cmd = "wc -l < file_1" # 读取wc的输出到变量 cmd | getline line_count # 关闭命令流 close(cmd) # 判断行数是否为0 if (line_count == 0) { print "something" } }' text.txt >> file_1
这种方式下,wc的输出会被捕获到line_count变量中,不会输出到stdout,只有符合条件的print内容会进入file_1。
方法B:直接用awk统计file_1的行数
完全不需要调用外部命令,直接用awk读取file_1并统计行数:
awk 'BEGIN { line_count = 0 # 逐行读取file_1 while ((getline < "file_1") > 0) { line_count++ } close("file_1") if (line_count == 0) { print "something" } }' text.txt >> file_1
这种方式更高效,也避免了外部命令带来的输出干扰问题。
内容的提问来源于stack exchange,提问作者YannickN.fr
相关产品推荐
相关产品推荐

