sed 用于在单个行上进行简单替换,仅此而已。如果您使用的是 s、g 和 p(带 -n)以外的 sed 结构,那么您使用的结构在 1970 年代中期 awk 被发明时就已经过时了。
$ awk '/^[[:alpha:]]/{f=$0;next} {print f","$0}' file
example.com,1.2.3.4
ftp.example.com,2.3.4.5
ftp.example.com,3.4.5.6
www.example.com,4.5.6.7
www.example.com,5.6.7.8
www.example.com,6.7.8.9
请注意这是多么清晰和简单,因为 awk 有变量,而 sed 没有。巧合的是,如果您关心它,它也比 sed 方法稍微简单一些,而且我敢打赌,如果您的文件很大,它的执行速度会更快。它还可以在所有操作系统上的所有 POSIX(由于 POSIX 字符类)awks 上可移植地工作,它不是特定于 GNU 的。
为了解决下面的评论,如果您希望每个 FQDN 的所有 IP 地址都在一行上,那么这是一种方法:
$ cat tst.awk
/^[[:alpha:]]/ { recs[++numFqdns] = $0; next }
{ recs[numFqdns] = recs[numFqdns] "," $0 }
END {
for (fqdnNr=1; fqdnNr<=numFqdns; fqdnNr++) {
print recs[fqdnNr]
}
}
$ awk -f tst.awk file
example.com,1.2.3.4
ftp.example.com,2.3.4.5,3.4.5.6
www.example.com,4.5.6.7,5.6.7.8,6.7.8.9
另外,这个 shell 脚本的直接 awk 翻译来自 skmrx 的回答:
while read line; do
if [[ $line =~ [^0-9.] ]]; then
echo -en "$pre$line"
else
echo -n ",$line"
fi
pre="\n"
done
应该是:
awk '{
if (/[^0-9.]/) {
printf "%s%s", pre, $0
}
else {
printf ",%s", $0
}
pre="\n"
}'
但是您永远不会真正在 awk 中编写,而是在 awk 中编写这种类型的逻辑的惯用方式是:
awk '{ printf "%s%s", (/[^0-9.]/ ? pre : ""), $0; pre=RS }'
您可以添加 END{print ""} 以打印 shell 脚本中缺少的最后一个换行符。