Bash - 更改文件配置格式

Bash - 更改文件配置格式

我想改变:

这:

client 192.168.100.1 {
    secret = ThisIStheSECRET
    shortname = HOSTNAME
}
client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}

那:

client HOSTNAME { secret = ThisIStheSECRET, ipaddr = 192.168.100.1 }
client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }

这个怎么做?使用什么工具?

答案1

一个简单的awk脚本:

awk '
    /^client/               { ipaddr    = $2                              }
    /^[[:blank:]]*shortname/{ shortname = $3                              }
    /^[[:blank:]]*secret/   { secret    = $0; sub("^[^=]*= ", "", secret) }
    /^}/ {
        printf("client %s { secret = %s, ipaddr = %s }\n",
            shortname, secret, ipaddr);
    }' file

当我们在输入文件中找到所需的信息时,只需解析出它们,当我们}在行开头点击 a 时,我们就会以正确的格式输出收集到的信息。

文本的解析secret很特殊,因为我们期望它包含任何事物,甚至字段分隔符。它只是首先将变量设置secret为整行,然后删除第一个空格之前的所有内容=以及此后的单个空格。

给定文件

client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}
client 10.0.0.1 {
    secret =     This is it, the secret!, ipaddr = 10.0.0.1
    shortname = myhost.local
}

(注意秘密开头的四个空格),这会产生

client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }
client myhost.local { secret =     This is it, the secret!, ipaddr = 10.0.0.1, ipaddr = 10.0.0.1 }

答案2

我会做类似的事情:

perl -0777 -pe 's{client\s+(\S+)\s*\{\s*(secret = .*)\s+shortname\s*=\s*(.*)\s*\}}
                 {client $3 { $2, ipaddr = $1 }}g'

答案3

这应该可以解决您的问题,尽管并不像我希望的那么“简单”:

perl -pe 's/(\w)\s*$/\1,\n/;' your_filename | perl -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;'

它运行一个正则表达式,在以字母数字结尾的行中添加逗号(A 到 Z、a 到 z、0 到 9 和 _)

它运行另一个正则表达式来用一个空格替换任何换行符(以及它们周围的空格),除非该行以 a 结尾}(利用负向后查找),然后最后运行一个用于最终格式化的正则表达式(切换主机名和 IP 并删除无关的内容)逗号)

这会忽略换行符,您可以将结果重定向到一个新文件(或现有文件)并> your_new_filename添加到末尾。如果您这样做,此解决方案可以使用一个-i标志来修改您的文件:

perl -i -pe 's/(\w)\s*$/\1,\n/;' your_filename
perl -i -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;' your_filename

答案4

我确信有更好的方法来解决这个问题,但我通过以下组合实现了sedawk

sed ':a;N;$!ba;s/\n/ /g' file | sed -e 's/    //g' -e 's/ client/\nclient/' | awk '{print $1" "$9" "$3" "$4" "$5" "$6",  ipaddress "$8" "$2" "$10}'

解释

  • sed ':a;N;$!ba;s/\n/ /g'用空格替换所有新行。参考这个这个答案了解更多信息
  • sed -e 's/ //g'将四个间隔块替换为一个空格。
  • -e 's/ client/\nclient/'当客户端字符串匹配时添加新行。
  • awk '{print $1" "$9" "$3" "$4" "$5" "$6", ipaddress "$8" "$2" "$10}'默认情况下,awk 用空格分隔文本,因此在这里您只需按照您想要的顺序打印主机名变量 ($9) 和 ip 地址变量 ($2)。您可以忽略“shortname”变量($7)并硬编码“, ipaddress”文本

相关内容