我想要一个这样的列表:
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
并解析为逗号分隔的CSV格式,以便在流行的电子表格程序中打开时,父fqdn位于a列,子ip位于b列。
我想使用本地的Linux二进制文件,这样我就可以嵌入到现有的BASH脚本中。
欢迎任何帮助,提前感谢。
这可能适合您(GNU sed):
sed -r '/[[:alpha:]]/h;//d;G;s/(.*)n(.*)/2,1/' file
如果该行包含字母字符,即是地址,将其存储在保持空间中,然后删除它。否则,将地址追加到当前行,然后交换两个字段,用,
替换换行符并打印
编辑:我看错了问题。下面我的解决方案打印主机名,然后是IP地址列表,而不是主机名+ IP地址对列表。
我将使用以下逻辑:对于每一行输入,- 如果文本包含IP地址以外的内容,则打印一个新的行字符,然后打印文本。不打印第一行文本的新行字符。
- 否则,打印逗号,然后再打印文本
例子:
Perl:perl -npe 'chomp; $_ = /[^d.]/ ? "$p$_" : ",$_"; $p="n"'
Bash :
#!/bin/bash
while read line; do
if [[ $line =~ [^0-9.] ]]; then
echo -en "$pre$line"
else
echo -n ",$line"
fi
pre="n"
done
sed用于单独行上的简单替换,仅此而已。如果您使用的是sed结构而不是s、g和p(带-n),那么您使用的是在20世纪70年代中期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
或者,从skmrx的答案直接翻译这个shell脚本:
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脚本中缺少的最后一个换行符。