[英]Using Sed Awk Bash to populate variable in search
我有几个包含多个部分的xml文件。 这些文件中的部分之一是“ PublishMgr”。 在本节下面,有两行包含服务器名称和端口。 我需要提取服务器和端口,并将它们放入变量并针对它们运行查询。 我真的不知道有什么简单的方法可以做到这一点。 我当时在考虑使用awk和sed,但是我对这些知识的了解是有限的。 你能帮忙吗?
我已经尽力将线条打印出来。 我可以使用awk -F获取第一个条目的主机名和端口号,但不确定第二行如何做? 如果可能,我希望一次扫描,而不是两次查询? 能做到吗?
请注意,我要将输出分配给4个不同的变量!
我的密码
cat filename | grep -A6 PublishMgr | grep "Address\|BacKMeUp"
XML-FILE / TXT仅文件的一部分
<<!--==========================================-->
<!-- PublishMgr -->
<!--==========================================-->
<goandpublishme>
<ClassPub name="buylimit" pers="Y">
<prime>host9:1000</prime>
<backup>host145:9999</backup>
</ClassPub>
电流输出
<prime>host9:1000</prime>
<backup>host145:9999</backup>
想要将结果分配给变量的所需输出请注意,我想将输出分配给4个“不同”变量。 因此,我可以将它们用于进一步的查询,就像一个简单的示例将是cd abc / $ srv1; grep ports $ srv1.log。 简而言之,我需要有$ srv1 $ srv2 $ port1 $ port2
srv1=host9
port1=1000
srv1=host145
port2=9999
这直接满足您所需的输出,并且基于您说您对sed和awk的了解有限的事实。
如果这是您当前的输出
<prime>host9:1000</prime>
<backup>host145:9999</backup>
然后,您可以通过添加带有多个表达式的sed命令并遍历行匹配项列表来获得所需的输出:
| sed -E -e "s/(^\s*)(<.[^>]*>)/srv$i=/g" -e "s/(<.[^>]*>)//g" -e "s/(:)/\nport$i=/g"
细分如下:
-e "s/(^\\s*)(<.[^>]*>)/srv$i=/g"
(^\\s*)
-行首,后跟无限制的空格 (<.[^>]*>)
-这些<>
以及中间的任何内容 /srv$i=/g
替换为srv,后跟增量编号。 -e "s/(<.[^>]*>)//g"
删除前导空格
-e "s/(:)/\\nport=/g"
用\\n
(换行)和port=
替换:
input.txt
,其中包含: <<!--==========================================-->
<!-- PublishMgr -->
<!--==========================================-->
<goandpublishme>
<ClassPub name="buylimit" pers="Y">
<prime>host9:1000</prime>
<backup>host145:9999</backup>
</ClassPub>
prime backup
遍历行匹配列表
i=1 ; for predicate in prime backup ; do grep -P "$predicate" <input.txt | sed -E -e "s/(^\s*)(<.[^>]*>)/srv$i=/g" -e "s/(<.[^>]*>)//g" -e "s/(:)/\nport$i=/g" ; (( i++ )) ; done
结果:
srv1=host9
port1=1000
srv2=host145
port2=9999
OLDIFS="$IFS" ; IFS=$'\n' ; for line in "$(i=1 ; for predicate in prime backup ; do grep -P "$predicate" <input.txt | sed -E -e "s/(^\s*)(<.[^>]*>)/srv$i=/g" -e "s/(<.[^>]*>)//g" -e "s/(:)/\nport$i=/g" ; (( i++ )) ; done)" ; do eval "$line" ; done ; IFS="$OLDIFS"
分解:
#!/bin/bash
OLDIFS="$IFS" #Save current IFS just for good measure
IFS=$'\n' #Set IFS to new-line
for line in "$(i=1
for predicate in prime backup
do grep -P "$predicate" <input.txt \
| sed -E -e "s/(^\s*)(<.[^>]*>)/srv$i=/g"\
-e "s/(<.[^>]*>)//g" \
-e "s/(:)/\nport$i=/g"
(( i++ ))
done)" #The original script broken into lines
do
eval "$line" #Actually assign the variables
done
IFS="$OLDIFS" #Restore IFS
echo "\$srv1 is: $srv1" #Print values of assigned variables
echo "\$srv2 is: $srv2"
echo "\$port1 is: $port1"
echo "\$port2 is: $port2"
通常,您不应使用sed
和awk
等面向行的工具来处理XML数据。 您应该改为使用支持XML的工具。 假设您的文档确实是有效的XML,则可以使用xmlstarlet
提取信息:
xmlstarlet sel -t -v 'concat("srv1=", substring-before(//ClassPub/prime, ":"))' -nl \
-t -v 'concat("port1=", substring-after(//ClassPub/prime, ":"))' -nl publish.xml
只需将prime
替换为backup
然后相应地调整字符串即可。 我怀疑您可能是说srv2
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.