【问题标题】:How to extract from a file text between tokens using bash scripts如何使用 bash 脚本从标记之间的文件文本中提取
【发布时间】:2011-02-01 08:05:54
【问题描述】:

我正在阅读这个问题:Extract lines between 2 tokens in a text file using bash 因为我有一个非常相似的问题...... 我必须在这个 xml 文件中提取(并在打印之前将其保存到 $variable)文本:

<--more labels up this line>
<ExtraDataItem name="GUI/LastVMSelected" value="14cd3204-4774-46b8-be89-cc834efcba89"/>
<--more labels and text down this line-->

我只需要获取 value=(显然没有括号,也没有'value='),但首先,我认为它必须搜索“GUI/LastVMSelected”才能到达这一行,因为可能有类似的值其他行中的字段,并且该标签的值是我想要的。

【问题讨论】:

  • 如果这是一个xml/html,你应该考虑使用合适的xml解析器

标签: bash unix scripting


【解决方案1】:

如果它们在同一行(就像您的示例中的那样),那就更容易了。只是:

sed -ne '/name="GUI\/LastVMSelected"/s/.*value="\([^"]*\)".*/\1/p'

解释:

  • -n:禁止默认打印
  • /name="GUI\/LastVMSelected"/:仅匹配此模式的行
  • s/.value="([^"])"./\1/p
    • 替换所有内容,捕获括号中的部分(value 的值)
    • 并打印结果

【讨论】:

  • 谢谢,它有效!但我需要在 $variable 中捕获它,因为我需要在脚本中使用它。
  • 那么为什么不直接使用varname=sed 随便``(注意反引号)?
  • 我找到了一个方法:VAR=$(sed -ne '/name="GUI\/LastVMSelected"/s/.*value="([^"]*)".*/\ 1/p' /some/place.xml) echo $VAR 这就是我想要的方式。现在我可以在脚本的某些部分使用变量 $VAR
【解决方案2】:

我假设您是从 XML 文档中提取的。如果是这种情况,请查看用于处理 XML 的 XMLStarlet 命令行工具。有一些用于查询 XML 文档的文档here

【讨论】:

    【解决方案3】:

    使用这个:

    for f in `grep "GUI/LastVMSelected" filename.txt | cut -d " " -f3`; do echo ${f:7:36}; done
    
    • grep 只为您提供您需要的线路
    • cut 使用一些分隔符拆分行,并返回拆分的第 N 个结果
    • -d " " 将分隔符设置为空格
    • -f3 返回第三个结果(基于 1 的索引)
    • ${f:7:36} 提取从索引 7 开始的子字符串,长度为 36 个字符。这消除了前导 value=" 和斜杠等。

    显然,如果字段的顺序发生变化,这将会中断,但如果您只是追求一些快速而肮脏的东西,那么应该就是这样。

    【讨论】:

    • 这不会去掉 value= 和引号。
    • 这取决于字符串在行中的特定位置,并且根本不可靠。它还打破了空白区域的排列,因此即使是这样它也不会起作用。
    • 我特意说过“如果字段的顺序改变了,就会中断”。在阅读免责声明后,没有人会认为这是可靠的。
    • 似乎使用 sed 可以获得最干净的输出,但我仍然需要在变量中捕获值,因为我需要在脚本中使用它。
    【解决方案4】:

    使用我对您链接的问题的回答:

    sed -n '/<!--more labels up this line-->/{:a;n;/<!--more labels and text down this line-->/b;\|GUI/LastVMSelected|s/value="\([^=]*\)"/\1/p;ba}' inputfile
    

    解释:

    • -n - 不要进行隐式打印
    • /&lt;!-- this is token 1 --&gt;/{ - 如果找到起始标记,则
      • :a - 标签“a”
        • n - 阅读下一行
        • /&lt;!-- this is token 2 --&gt;/q - 如果是结束标记,退出
        • \|GUI/LastVMSelected| - 如果该行与字符串匹配
          • s/value="\([^"]*\)"/\1/p - 在 'value=' 之后和下一个引号之前打印字符串
      • ba - 分支到标签“a”
    • }结束如果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-18
      • 2014-04-26
      • 1970-01-01
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多