如何用awk忽略输入文件IN-arg中的注释内容?
AWK去除文件注释的实现方案
问题拆解
你需要处理输入文件IN-arg,去掉所有#开头的注释内容,保留注释前的文本和原有的缩进格式,同时跳过纯注释行(比如第一行)。
你的现有代码存在的问题
- 逐个打印字段会导致每个字段单独换行,完全不符合预期的整行输出格式
- 判断
$i == "#"仅匹配单独作为字段的#,但实际注释的#常和后面内容连在一起(比如#this is also a comment是一个独立字段),根本触发不了截断逻辑 - 没有处理纯注释行,这类行应该被跳过而不是输出
两种可行的解决方法
方法一:用sub快速替换注释(最简洁)
直接用sub函数匹配每行中第一个#及其后续所有内容,替换为空,再过滤掉纯空行即可,还能完美保留行首缩进。
代码如下:
#!/bin/awk -f { # 把第一个#及后面的所有内容替换为空 sub(/#.*/, "") # 打印非空行(含仅缩进的行,跳过纯注释的空行) if ($0 !~ /^[[:space:]]*$/) { print } }
说明:
sub(/#.*/, ""):sub是AWK的字符串替换函数,只会替换第一个匹配项,刚好对应每行的第一个注释起始位置- 条件
$0 !~ /^[[:space:]]*$/:确保只打印有实际内容(包括缩进)的行,纯注释处理后变成空行,直接跳过
方法二:字段遍历截断(修正你的思路)
如果想沿用你遍历字段的思路,需要调整判断逻辑,检查字段是否以#开头,同时保留行首缩进:
#!/bin/awk -f { # 提取行首的缩进字符 indent = substr($0, 1, index($0, $1) - 1) content = "" for (i=1; i<=NF; i++) { # 遇到以#开头的字段,立即停止遍历 if ($i ~ /^#/) { break } content = content $i " " } # 去掉末尾多余空格,拼接缩进后打印(仅当有内容时) if (content != "") { print indent substr(content, 1, length(content)-1) } }
说明:
- 先提取行首缩进,保证输出格式和原文件一致
- 遍历字段时,只要发现某个字段以
#开头,就截断后续字段 - 拼接有效字段后去掉末尾多余空格,加上缩进再打印,避免输出多余空格
测试结果
用你的输入文件IN-arg测试上述任意一段代码,都会得到你预期的输出:
joejoejoe 10 20 30 OAK -999 10 joeJOE 2000 oak 10 milk 1000
内容的提问来源于stack exchange,提问作者willy
相关产品推荐
相关产品推荐

