【问题标题】:Simple Regex not working in Perl简单的正则表达式在 Perl 中不起作用
【发布时间】:2013-12-05 18:11:24
【问题描述】:

我有一个简单的 Perl 正则表达式,它应该匹配两个字符之间的空格并将空格替换为 *。在某些情况下它根本不起作用。 Perl 行是这样的:

s/([A-Za-z0-9])\s+([A-Za-z0-9])/\1 * \2/g;

例如见下图:(~> 是我的 zsh 提示符)

~> cat mwe
s t Subscript[r, 1]
~> perl -pe "s/([A-Za-z0-9])\s+([A-Za-z0-9])/\1 * \2/g;" < mwe
s * t Subscript[r, 1]

t Subscript[r, 1] 不匹配。这只是一个例子。我的文件更长,虽然正则表达式捕获最正确,但我找不到与它不匹配(并且应该)匹配的模式。

Vim 似乎可以正确找到所有内容(在适当的正则表达式语法更改之后)。

我该如何解决这个问题?我如何帮助诊断问题?

谢谢。

【问题讨论】:

  • s Subscript: 无法匹配,因为您之前匹配了t s,所以s 已经“使用”并且不再查看...您需要另一个通过得到那个。最后一个 t subScript 也是一样的:t 用于前面的替换,下一个搜索在它之后开始。您可以取出“g”并循环,直到没有替换为止。
  • 不要在替换表达式中使用 \1 和 \2。 \1 和 \2 仅在正则表达式模式中才有意义,因为它们的意思是匹配第一次和第二次捕获的内容。请改用 $1 和 $2。
  • @ikegami 但我想要第一次和第二次捕获的内容。 (我没有说错 - \1 与 $1 是我显然很困惑的东西)
  • 我知道,但我不是这么说的。你从我所说的中去掉了“匹配”这个词。您想要“[插入]第一次和第二次捕获捕获的内容”,这与想要“匹配第一次和第二次捕获捕获的内容”不同
  • 好的。谢谢你的提醒。我在这里找到了更多信息:stackoverflow.com/questions/1068840/…

标签: regex perl


【解决方案1】:

改用前瞻:

perl -pe 's/([a-z0-9])\s+(?=[a-z0-9])/\1 * /ig' mwe

输出:

s-E^(t * 下标[r, 1]) t * v-E^(t * 下标[r, 1]) y-E^(t * 下标[r, 1]) t * y+E^t * s * 下标[r, 1]+2 * E^(t * 下标[r, 1]) s * 下标[r, 1]-3 * E^(t+t * 下标[r, 1]) s * 下标[r, 1]+E^(t * 下标[r, 1]) s * t * 下标[r, 1]

问题是在你的正则表达式中你匹配的不是向前看。所以对于以下情况:

perl -pe 's/([a-z0-9])\s+([a-z0-9])/\1 * \2/ig' <<< "a b c"

你会得到:

a * b c

因为b 之前已经匹配过并且内部指针已经向前移动了。

【讨论】:

  • 好的,谢谢。虽然这行得通,但你能告诉我为什么我的行不通吗?
  • 前瞻不会改变正则表达式匹配的位置,所以左括号可以第二次匹配t。如果没有前瞻,t 在第一场比赛中被消耗。
  • 正则表达式是“懒惰的”,它不会在第一场比赛中停止,它会寻找最后可能的比赛,所以我相信你的情况,它会在到达你正在寻找的点之前停止
  • @bkanuka:我在回答中添加了一些解释。
  • +1,很好的解决方案。它接近原始版本,并显示何时使用前瞻。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多