我想要创建一个具有特定配置的.xml文件,这个配置需要一个主机名和一个ip,我已经创建了hosts.csv来输入这些数据,它们是.csv file上的每个分隔行的vm-tmb-test1;127.0.0.1,";"是服务器的主机名和ip,但是在hosts.csv中为每个ip创建了循环打印。
码结构
#!/bin/bash
for i in $(cat /var/projects/etc/hosts.csv | cut -d\; -f1)
do
for ips in $(cat /var/projects/etc/hosts.csv | cut -d\; -f2)
do
if [[ ${i} == *"jua"* ]]
then
sed -i '$ a <node name="'${i}'" tags="infra,jua,vm" hostname="'${ips}'" username="test"/>' /var/projects/etc/resources.xml
elif [[ ${i} == *"tmb"* ]]
then
sed -i '$ a <node name="'${i}'" tags="infra,tmb,vm" hostname="'${ips}'" username="tests"/>' /var/projects/etc/resources.xml
fi
done
doneHost.csv内容:
vm-tmb-test1;127.0.0.1
vm-tmb-test2;127.0.0.2
vm-tmb-test3;127.0.0.3
vm-jua-test4;127.0.0.4期望产出:
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test3" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-jua-test4" tags="infra,jua,vm" hostname="127.0.0.4" username="test"/>实际代码输出:
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.4" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.4" username="test"/>我怎么才能解决呢?
编辑1: host.csv包含更多的200台服务器,主机名和ip,它将随着时间的推移而提供。
发布于 2021-03-11 20:49:30
虽然存在更快的解决方案(例如,awk、sed),但对于这个答案,我将坚持OP使用循环的想法。
样本输入:
$ cat host.csv
vm-tmb-test1;127.0.0.1
vm-tmb-test2;127.0.0.2
vm-tmb-test3;127.0.0.3
vm-jua-test4;127.0.0.4由于示例代码似乎只是将输出附加到一个*.xml文件中,所以我将选择一个生成所需输出的while循环:
while IFS=";" read -r i ips # use ';' as input delimiter and read values into our 2 variables 'i' and 'ips'
do
tag='UNDEFINED' # define some defaults in case 'i' does not
uname='UNDEFINED' # have a match in our case statement
case "${i}" in # pattern match 'i' to determine what strings to submit to the printf command
*jua*) tag='jua' ; uname='test' ;;
*tmb*) tag='tmb' ; uname='tests' ;;
esac
printf '<node name="%s" tags="infra,%s,vm" hostname="%s" username="%s"/>\n' "${i}" "${tag}" "${ips}" "${uname}"
done < host.csv以上所述产生:
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="tests"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="tests"/>
<node name="vm-tmb-test3" tags="infra,tmb,vm" hostname="127.0.0.3" username="tests"/>
<node name="vm-jua-test4" tags="infra,jua,vm" hostname="127.0.0.4" username="test"/>注意到
destination
printf的输出重定向到最终的printf,这比重复的sed -i调用username="{test|tests}"的使用(尽管OP的示例输出仅显示字符串test);OP可以根据需要编辑建议的代码(< code >F 220)
发布于 2021-03-11 19:49:48
一个GNU sed调用可以完成以下工作:
sed -E 's/([^-]*)-([^-]*)-([^;]*);(.*)/<node name="\1-\2-\3" tags="infra,\2,\1" hostname="\4" username="test"\/>/' file发布于 2021-03-11 21:05:22
将while循环解决方案推入单个awk调用:
awk -F";" ' # input delimiter is ";"
{ tag="UNDEFINED" } # default tag in case $1 does not match the following patterns
$1 ~ /jua/ { tag="jua" }
$1 ~ /tmb/ { tag="tmb" }
{ printf "<node name=\"%s\" tags=\"infra,%s,vm\" hostname=\"%s\" username=\"test\"/>\n", $1, tag, $2 }
' host.csv这就产生了:
<node name="vm-tmb-test1" tags="infra,tmb,vm" hostname="127.0.0.1" username="test"/>
<node name="vm-tmb-test2" tags="infra,tmb,vm" hostname="127.0.0.2" username="test"/>
<node name="vm-tmb-test3" tags="infra,tmb,vm" hostname="127.0.0.3" username="test"/>
<node name="vm-jua-test4" tags="infra,jua,vm" hostname="127.0.0.4" username="test"/>注意到
再次,OP可以将username="test"的输出重定向到最终的输出文件(或者,将awk调用的全部输出定向到所述输出文件)
https://stackoverflow.com/questions/66589388
复制相似问题