【问题标题】:Using Sed Awk Bash to populate variable in search使用 Sed Awk Bash 在搜索中填充变量
【发布时间】:2017-11-12 04:09:36
【问题描述】:

我有几个包含多个部分的 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 端口 $srv1.log。总之我需要有 $srv1 $srv2 $port1 $port2

srv1=host9    
port1=1000    
srv1=host145
port2=9999  

【问题讨论】:

  • 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。
  • 发布一个带有有效 XML 的示例。

标签: arrays bash awk sed cut


【解决方案1】:

这直接迎合您想要的输出,并且基于您说您对 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*)(&lt;.[^&gt;]*&gt;)/srv$i=/g"

  • (^\s*) - 行首后跟无限空格
  • (&lt;.[^&gt;]*&gt;) - 这些&lt;&gt; 以及介于两者之间的任何东西
  • /srv$i=/g - 替换为 srv,后跟增量号。

-e "s/(&lt;.[^&gt;]*&gt;)//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 <strong>prime backup</strong> ; do grep -P "$predicate" &lt;<strong>input.txt</strong> | sed -E -e "s/(^\s*)(&lt;.[^&gt;]*&gt;)/srv$i=/g" -e "s/(&lt;.[^&gt;]*&gt;)//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 cmets 可以工作,但我需要将输出分配给 4 个不同的变量。如果我在问题的描述中不清楚,我很抱歉。我已经更新了它。我需要使用这些变量来做进一步的查询。谢谢
  • @theuniverseisflat 看看我的编辑,现在你的要求更清楚了
  • @theuniverseisflat 鉴于您的 input.txt 看起来与演示的相同,请使用以下行:i=1 ; for predicate in prime backup ; do grep -P "$predicate" &lt;input.txt | sed -E -e "s/(^\s*)(&lt;.[^&gt;]*&gt;)/srv$i=/g" -e "s/(&lt;.[^&gt;]*&gt;)//g" -e "s/(:)/\nport$i=/g" ; (( i++ )) ; done
  • 问题是我无法将这些输出分配给变量。我现在可以使用 sed 或 awk 命令获取输出,但 VAR 分配不起作用。请参阅stackoverflow.com/questions/44545583/…
  • @theuniverseisflat 查看底部的更新。完成。
【解决方案2】:

一般来说,您不应使用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

【讨论】:

  • 谢谢,我要试试。是的,它是 xml 格式的文件/我让你知道
  • 我需要生成 4 个不同的变量,以便稍后在脚本中使用。
  • srv1="host9" port1="1000" srv2=host145 port2=9999
猜你喜欢
  • 2019-01-17
  • 2014-06-08
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多