![Bash - 更改文件配置格式](https://linux22.com/image/132174/Bash%20-%20%E6%9B%B4%E6%94%B9%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE%E6%A0%BC%E5%BC%8F.png)
我想改变:
这:
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
我确信有更好的方法来解决这个问题,但我通过以下组合实现了sed
它awk
。
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”文本