regex - 如何使用 bash 中的 grep 停止贪婪

标签 regex bash grep

我有一个包含以下内容的 html 页面:

[...]
<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr>
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td></tr>
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td></tr>
[...]

我只想提取

play-1.0.1.zip
play-1.0.2.1.zip
play-1.0.2.zip

然后找到最新版本(在本例中为 play-1.0.2.1.zip)

所以我尝试了

cat tmp.html | grep "<a href=\".*\""

<a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="m"
<a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="m"
<a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="m"

所以我尝试了 lazy:

cat tmp.html | grep "<a href=\".*?\""

并否定引号

cat tmp.html | grep "<a href=\"[^\"]*?\""

两者都没有返回

我只需要获取匹配的部分(不是 href),然后找到最新的,但我被这个贪心问题困住了......

--

非常感谢所有的答案,它们都非常有用,很难决定哪个是正确的,最后我解决了:

grep -v '.*-RC.*' index.html | grep -oP 'play-1.*?.zip' | sort -Vru | head -1

最佳答案

与其他答案相反,这完全可以用 grep 完成。

您的输出与您的输入略有不同 - 出现了额外的元素。出于这个答案的目的,我将使用这个文件:

<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr>
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr>
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr>

这里有几件事你需要做。首先,您需要设置正确的 grep 开关。你需要:

  • -o 只输出每行匹配的部分
  • -P 使用兼容 Perl 的正则表达式引擎

现在您可以使用 ?防止贪婪匹配的修饰符:

grep -o -P '<a href=".*?"' test.html

<a href="play-1.0.1.zip"
<a href="play-1.0.1.zip"
<a href="play-1.0.2.1.zip"
<a href="play-1.0.1.zip"
<a href="play-1.0.2.zip"
<a href="play-1.0.1.zip"

这不太正确,所以我们将正则表达式锚定到该行的第一个匹配项:

grep -o -P '^<tr><td class="n"><a href=".*?"' test.html

<tr><td class="n"><a href="play-1.0.1.zip"
<tr><td class="n"><a href="play-1.0.2.1.zip"
<tr><td class="n"><a href="play-1.0.2.zip"

这是正确的数据,但有太多的废话。我们需要使用的是零宽度断言(PCRE 语法的一部分)。本质上是一些不计入匹配模式的正则表达式。

grep -o -P '(?<=^<tr><td class="n"><a href=").*?(?=")' test.html

play-1.0.1.zip
play-1.0.2.1.zip
play-1.0.2.zip

现在您可以根据需要对列表进行排序。可以在此处找到有关零宽度断言的更多信息:http://www.regular-expressions.info/lookaround.html

关于regex - 如何使用 bash 中的 grep 停止贪婪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9720249/

相关文章:

c# - 用字母变量替换数学方程式中的 float

html - 正则表达式以匹配第一个结束的 HTMl 标记

perl - 如何使正则表达式与 perl 命令一起使用并从文件中提取数字?

javascript - 自动替换 RegEx JavaScript 中的参数

linux - bash 中的简单 while 循环

python - 如何在Python中调用一系列bash命令并存储输出

bash - 删除所有包含插入符号 (^) 的行

bash - 从文件中的特定行以相反的顺序 Grep 文件

linux - 如何使用 sed 打印匹配组

php - 正则表达式匹配组前面没有字母数字 (\w),忽略空格