正则表达式匹配单词的第一个实例,但仅在匹配来自另一个模式之前

时间:2015-05-04 18:11:46

标签: regex postgresql posix

我找到了一些关于在字符串中查找单词的第一个实例的信息,但是我试图找到一个单词的第一个实例(实际上是两个,但是在单独的调用中)只有在它之前一些非常具体的文本(由下划线分隔的IP地址)略有不同。此外,这些单词由下划线分隔,因此由于某种原因\b对我不起作用。

这是一些示例字符串,用于一次测试一行。只应匹配粗体字。

  • 192_168_10_2_的 02_port01_other_text_with_card_or_port
  • 10_22_1_200_的 4_port5_another_string_with_port_or_card
  • something_else_with_card_or_port_in_it

在第二次通话中,我想在这些字符串中匹配不同的单词。

  • 192_168_10_2_card02_的端口 01_other_text_with_card_or_port
  • 10_22_1_200_card4_的端口 5_another_string_with_port_or_card
  • something_else_with_card_or_port_in_it

我的正则表达式是POSIX正则表达式(对于PostgreSQL 9.4)。到目前为止,我已经能够运行在http://regexpal.com/这里工作的任何东西了。

即使它不能同时解决所有3个例子,如果它可以解决前两个例子,那将非常有帮助。

编辑:为了绝对清楚,我的意图是用字符'c'替换第一个字符串'card',然后用字母'p'替换第一个字符串'port'而不影响'card'的任何实例'或'端口'没有紧跟数字。这就是为什么我的比赛只需要包含没有相应数字的第一个单词。

3 个答案:

答案 0 :(得分:1)

如果您可以使用否定前瞻,则可以使用card((?!port).)*port将字符串与卡匹配,而不是任何数量的字符后跟端口,然后再次使用卡。

编辑:

如果输入始终采用相同的格式,则可以使用card[0-9]{1,2}_port更具体。这将使其不与任何其他无关的卡和端口实例匹配

EDIT2:

只匹配第一种情况中的单词,您可以使用正向前瞻:card(?=[0-9]{1,2}_port)。我不确定你的味道是否允许积极的外观(测试人员没有,但这是在js),但给(?<=card[0-9]{1,2}_)port一个镜头。如果积极的外观不起作用,您可能需要研究替代方案。

答案 1 :(得分:0)

\b断言在这种情况下不起作用,因为_被认为是单词字符。

Demo

您可以使用背后的外观:

(?<=_)(card).*?(?<=_)(port)

Demo

更具体地说,使用IP地址模式:

(^(?:\d+_){4})(card\d+)_(port\d+)

Demo

答案 2 :(得分:0)

我必须分两步解决这个问题。在第一个中,我在开头只匹配了带有IP字符串的行(这排除了像我的第3个例子那样的行)。在第二步中,我使用regexp_replace替换每个单词的第一个匹配。

不幸的是,我完全错过了regexp_replace只替换第一场比赛的事实,除非另有说明&#39; g&#39;标志:

WHEN (SELECT regexp_matches(mystring, '^1(?:[0-9]{1,3}_){4}card[0-9]{1,2}_port[0-9]{1,2}')) IS NOT NULL
  THEN regexp_replace(regexp_replace(mystring, 'card', 'c'), 'port', 'p')

虽然我仍然希望我能弄清楚如何在单个表达式中匹配其中一个单词,但我会接受任何可以达到此目的的答案。