繁体   English   中英

使用Sed Awk Bash在搜索中填充变量

[英]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"

通常,您不应使用sedawk等面向行的工具来处理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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM