将FQDN和IP列表转换为两列CSV

时间:2015-10-02 22:34:10

标签: linux bash csv awk sed

我想要这样的列表:

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脚本进行烘焙。

欢迎任何帮助,并提前致谢。

3 个答案:

答案 0 :(得分:1)

编辑:我错误地阅读了这个问题。我的解决方案下面打印主机名,然后打印IP地址列表,而不是主机名+ IP地址对列表。

我会使用以下逻辑:对于每行输入,

  1. 如果文本中包含IP地址以外的内容,请打印新的行字符,然后打印文本。第一行文字不会打印换行符。
  2. 否则,请打印逗号,然后打印文本
  3. 示例:

    的Perl:

    perl -npe 'chomp;  $_ = /[^\d.]/ ? "$p$_" : ",$_"; $p="\n"'
    

    击:

    #!/bin/bash
    
    while read line; do
        if [[ $line =~ [^0-9.] ]]; then
            echo -en "$pre$line"
        else
            echo -n ",$line"
        fi
        pre="\n"
    done
    

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r '/[[:alpha:]]/h;//d;G;s/(.*)\n(.*)/\2,\1/' file

如果该行包含字母字符,即地址,则将其存储在保留空间中,然后将其删除。否则,将地址附加到当前行,然后交换两个字段,用,替换换行并打印。

答案 2 :(得分:1)

sed用于单个行上的简单替换,即全部。如果你使用s,g和p以外的sed结构(带-n)那么你使用的结构在20世纪70年代中期发明时已经过时了。

$ 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

Alterantively,这个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脚本中缺少的最终换行符。