【问题标题】:Select a string between two others strings in a file BASH [duplicate]在文件 BASH 中的其他两个字符串之间选择一个字符串 [重复]
【发布时间】:2020-04-14 07:38:27
【问题描述】:

我知道有些人问了同样的问题,但我没有得到任何结果, 这是我的文字:

<html>
<head>
<title>emdee five for life</title>
</head>
<body style="background-color:powderblue;">
<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>PeKPATbxnupBGgWTIg5B</h3><center><form action="" method="post">
<input type="text" name="hash" placeholder="MD5" align='center'></input>
</br>
<input type="submit" value="Submit"></input>
</form></center>
</body>
</html>

我想从中提取“PeKPATbxnupBGgWTIg5B”。 我在做sed -n "/^h3 align ='center'&gt;$/,/^&lt;h3$/p" thefile 但它没有返回任何东西。 请帮帮我:(

【问题讨论】:

  • 请发布有效的 HTML。
  • Don't Parse XML/HTML With Regex. 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。
  • 我们不需要 HTML 是有效的,我只想从中提取一个字符串。如果我的文本是“This is a text”并且我将提取“This”和“text”之间的字符串,那将是相同的。 (对不起,如果我的英语不好,我来自法国)
  • 我只是想知道为什么我的 bash 命令没有从我的文本中提取“PeKPATbxnupBGgWTIg5B”。

标签: bash awk sed grep


【解决方案1】:

正确的方法是使用 XML/HTML 解析器。

如果你的文字是

...
<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>PeKPATbxnupBGgWTIg5B
</h3><center><form action="" method="post">
...

然后

sed -n "/<h3 align='center'>/,/^<\/h3>/p" thefile

会回来

<h1 align='center'>MD5 encrypt this string</h1><h3 align='center'>PeKPATbxnupBGgWTIg5B
</h3><center><form action="" method="post">

这不是你想要的。 /&lt;start&gt;/,/&lt;end&gt;/ 形式匹配不同行上 &lt;start&gt;&lt;end&gt; 之间的所有内容。

您可以使用使用反向引用的替换来匹配您想要的字符串,例如

sed -n "s/.*<h3 align='center'>\(.*\)<\/h3>.*/\1/p" thefile

返回

PeKPATbxnupBGgWTIg5B

使用支持 perl 兼容正则表达式 (PCRE) 的 grep,您可以使用

grep -P -o "<h3 align='center'>\K.*(?=</h3>)" thefile
  • -P 启用 perl 兼容的正则表达式
  • -o只打印匹配的部分
  • &lt;h3 align='center'&gt;\K 使用正向后视,\K 用于匹配不包含在匹配项中的 &lt;h3 align='center'&gt;
  • .* 匹配任意字符
  • (?=&lt;/h3&gt;) 使用正向前瞻来匹配未包含在匹配项中的 &lt;/h3&gt;

【讨论】:

    【解决方案2】:

    sed 命令sed -n '/pattern1/,/pattern2/p 确实可以提取 pattern1pattern2 之间的行 if 他们是 位于单独的行中。
    比如下面的测试代码:

    cat <<EOS | sed -n '/pattern1/,/pattern2/p'
    foo
    bar
    pattern1
    These lines
    are printed.
    pattern2
    baz
    EOS
    

    输出:

    pattern1
    These lines
    are printed.
    pattern2
    

    但是,如果模式是 位于同一行。 此外,插入符号^ 和美元符号$ 匹配开头 和行尾。他们没有指明位置 要匹配的子字符串。

    您是否可以尝试以下方法:
    (不用说我不打算用 sed 解析 XML 文件。这个 只是使用sed 提取子字符串的案例研究。)

    sed -n "s/.*h3 align='center'>\([^<]*\)<\/h3.*/\1/p" thefile
    

    模式.*h3 align='center'&gt;\([^&lt;]*\)&lt;\/h3.* 匹配:

    • 包含h3 align='center' 和任何前面的子字符串 字符回到字符串的开头。
    • 后跟一系列任意字符,不包括&lt;
    • 后跟一个包含&lt;/h3 和任何尾随的子字符串 直到行尾的字符。

    然后s(替代)命令将匹配的模式替换为 上面的第二个子字符串。它适用于extract 第二个子字符串 从匹配的行开始。

    让我详细介绍一下第二个模式\([^&lt;]*\)

    • 字符类[^&lt;] 匹配除&lt; 之外的任何字符。
    • 概念other than &lt;是锚定模式匹配所必需的 就在以下子字符串 &lt;/h3 之前。否则匹配 由于其性质,可能会在它上面运行下一个子字符串&lt;/h3 greedy match.
    • 星号*是确定重复次数的量词 的前一个原子。在这种情况下,它匹配更长的子字符串 比 0 由除&lt; 以外的任何字符组成。
    • 周围的括号 \(\) 创建 capture group 和 被包围的子字符串可以用\n 引用(其中 n 是一个数字 按出场顺序)作为替代品。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2021-12-21
      • 2019-12-20
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多