【问题标题】:Why is the positive lookahead in my pcregrep Regex not working?为什么我的 pcregrep 正则表达式中的积极前瞻不起作用?
【发布时间】:2019-05-31 18:18:37
【问题描述】:

我使用 pcregrep 编写了一个正则表达式,一切都按预期运行,直到我添加了一个积极的前瞻。

场景:

我有以下文本文件:

a
b
c
a
c

目标:

我想使用带有 pcregrep 的正则表达式来返回包含a 的行和包含c 的行以及它们之间包含b 的行,但没有被捕获。因此它将捕获前三行(abc)并返回第一行(a)和第三行(c)。它不会捕获第四行和第五行,因为它们之间没有b 行。所以输出将是:

a
c

我的尝试

如果我运行 pcregrep -M 'a\nb\nc\n'command 1),它会捕获并返回:

a
b
c

正如预期的那样。所以我现在想修改它以捕获b 行,并具有积极的前瞻性。我试过这个:pcregrep -M 'a\n(?=(b\n))c\n'command 2)。但是,这不会返回任何内容。

我的问题:

为什么 command 2 没有返回预期的输出,而 command 1 会返回?如何返回所需的结果?我知道除了pcregrep 之外还有其他方法可以做到这一点,但请注意我想使用pcregrep,因为我将扩展功能以解决类似问题。

谢谢!

【问题讨论】:

  • 请记住,使用前瞻时,您不会不匹配前瞻中的字符。您只断言(不匹配字符)前瞻模式存在。您仍然必须匹配整个模式,并且前瞻再次匹配,仅断言。
  • @K.Dᴀᴠɪs 明白了,谢谢。所以我现在尝试使用非捕获组,如下所示:pcgrep -M 'a\n(?:(b\n))c\n'。然而,这仍然返回'a'、'b'、'c'。你知道我怎样才能让它只返回'a''c'吗?

标签: regex pcre regex-lookarounds pcregrep


【解决方案1】:

您可以通过-o 选项使用 2 个捕获组:

pcregrep -M -o1 -o2 '(a\n)b\n(c)\n' file

a
c

详情:

  • (...):在正则表达式中,它用于捕获组
  • -o1 -o2:仅打印捕获组 #1 和 #2

请注意,您的正则表达式 a\n(?=(b\n))c\n 将不起作用,因为前瞻只是零宽度匹配的断言。您的正则表达式在a\n 之后断言b\n 的存在,这很好,但它会尝试匹配c\n a\n 之后,这就是匹配失败的地方。

【讨论】:

  • 是的,我在我的回答中写到-o 打印only-matching 匹配字符串的一部分,-oN 打印捕获组#N
  • 最后澄清一下,如果我不想在中间有一行b,而是想有任意数量的b 行怎么办?目前我只有b\n,但要有零个或更多这样的行,我想我必须做(b\n)*,对吧?但我不希望括号内的b\n 被捕获。用你给我的策略我会怎么做?
  • ...我是否也必须将其视为捕获组,然后执行 -o1 -o3 以忽略中间的?
  • 1.您可以使用非捕获组来保持组编号相同:pcregrep -M -o1 -o2 '(a\n)(?:b\n)+(c)\n' f。 2.nested parentheses号码从左括号开始。
  • 我知道怎么做.. 可以通过--om-separator=","
【解决方案2】:

为什么命令 2 没有返回预期的输出,而命令 1 却返回了? 因为命令2是不同的表达方式

(?=…) 是零宽度前瞻

您指定的是:我想要一个a,然后是一个换行符,然后是一个b,然后是一个换行符。在那个位置,我还想要一个c,后跟一个换行符。

附:只是得到 a 和 c 也许这会有所帮助?

pcregrep -M 'a\nb\nc\n' | pcregrep -M 'a|c'

【讨论】:

  • 明白,谢谢。所以我现在尝试使用非捕获组,如下所示:pcgrep -M 'a\n(?:(b\n))c\n'。然而,这仍然返回 'a'\n, 'b'\n, 'c'\n。你知道我怎样才能让它只返回 'a'\n 'c'\n?
  • 我在回答@gkeenley 中添加了一个提案
  • 这确实有效!你能解释一下“|”背后的逻辑吗?在那里工作?
  • 第二个pcregrep 可以替换为grep -E '^(a|c)$' 但IMO 使用多个命令来实现这一点效率低下
  • @gkeenley 第一个 pcregrep 吐出到标准输出。管道(“|”)将标准输出作为标准输入提供给第二个 pcregrep。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多