如何在正则表达式中忽略转义括号

时间:2019-03-09 16:56:06

标签: regex grep

我正在尝试使用正则表达式从PDF中提取一些自定义属性(我将使用grep)。

PDF自定义属性是以以下格式存储的键值:

<</key1(value1)/key2(value2)/key3(value3)>>

内部值的括号被转义:

/key4(outside \(inside\) outside)

我执行了以下正则表达式来提取键的值:

grep -Po '(?<=key4\().*?(?=\))' "sample.txt"

但是,将其应用于key4(带有括号)时,会产生:

outside \(inside\

因为它停在第一个)(已转义的那个)中,而不是未转义的那个。

如何在正则表达式中忽略转义的括号?

谢谢。

PD:我愿意接受sed或awk中的建议。

3 个答案:

答案 0 :(得分:1)

您可以这样做

(?<=key4\()[^\\()]*(?:\\[\S\s][^\\()]*)*(?=\))

https://regex101.com/r/B4qKdh/1

展开:

 (?<= key4\( )
 [^\\()]* 
 (?: \\ [\S\s] [^\\()]* )*
 (?= \) )

答案 1 :(得分:1)

您可以使用类似{p>的sed解决方案

sed 's/.*key4(\([^\()]*\(\\.[^\()]*\)*\)).*/\1/'
sed -E 's/.*key4\(([^\()]*(\\.[^\()]*)*)\).*/\1/'

请参见online sed demo

POSIX ERE模式详细信息

  • .*-任意0个以上的字符
  • key4\(-key(文字字符串
  • \( - a(`char
  • ([^\()]*(\\.[^\()]*)*)-第1组:
    • [^\()]*-除\()以外的0个或更多字符
    • (\\.[^\()]*)*-重复0次或更多次
      • \\.-一个\后跟任意1个字符
      • [^\()]*-除\()以外的0个或更多字符
  • \)-一个)字符
  • .*-任意0个以上的字符

请注意,POSIX BRE模式仅交换了文字和捕获括号(转义了捕获括号(POSIX BRE中的(与文本(字符匹配,它不是捕获组的开始)。

替换部分中的\1是第1组占位符,并用该组值替换整个匹配项。

答案 2 :(得分:0)

在任何UNIX盒子上的任何外壳中都有任何awk:

$ awk '
    { gsub(/\\[(]/,"\n1"); gsub(/\\)/,"\n2") }
    match($0,/[/]key4[(][^)]+/) {
        $0 = substr($0,RSTART+6,RLENGTH-6)
        gsub(/\n1/,"\\("); gsub(/\n2/,"\\)")
        print
    }
' file
outside \(inside\) outside

使用GNU awk将第三个参数匹配():

$ awk '
    { gsub(/\\[(]/,"\n1"); gsub(/\\)/,"\n2") }
    match($0,/[/]key4[(]([^)]+)/,a) {
        $0 = a[1]
        gsub(/\n1/,"\\("); gsub(/\n2/,"\\)")
        print
    }
' file
outside \(inside\) outside

以上内容仅将\(\)替换为包含换行符的字符串(在换行符分隔的记录中不存在)\n1\n2,然后找到key4的匹配项,然后在打印之前将替换字符串放回其原始值。