正则表达式,其中括号可能不平衡

时间:2017-02-17 00:39:53

标签: regex regex-lookarounds

我必须将一些文本作为字符串从PDF流中提取出来。此流将包含用于描述文本外观的标记和文本本身。我收到的正则表达式必须运行的字符串将永远不会包含任何回车符或换行符。我感兴趣的文本区域将始终在括号内(并且在括号内可能有括号),并且在最后的括号之后将有字母'Tj'。简而言之,我所追求的将永远遵循惯例:

(.....) Tj

目前,我所使用的正则表达式正在工作,只要括号全部平衡:

\((?:[^()]|(?'paren'\()|(?'-paren'\)))+(?(paren)(?!))\)

然而,如果文本本身包含不平衡的parethesis,这个正则表达式将不会拉我想要的,我不知道如何更改它以能够处理不平衡的括号。

以下是一个被视为“普通”字符串的示例:

q  Q  /Tx BMC  q  0 0 471.34 407.34 re  W  n  BT  1 0 0 1 2 397.16 Tm  /Helv 12 Tf  0 g  (RE:  Request for Additional Information) Tj

很明显,我希望得到字符串'RE:Request for Additional Information'。

这是一个示例,我的正则表达式将失败(我添加了不平衡的括号):

q  Q  /Tx BMC  q  0 0 471.34 407.34 re  W  n  BT  1 0 0 1 2 397.16 Tm  /Helv 12 Tf  0 g  (RE:  Request for (Additional Information) Tj 0 g  1 0 0 1 2 383.29 Tm  0 g  (     13. Processing TT Instructions -) Audit Note 12) Tj  0 g  1 0 0 1 2 369.42 Tm  0 g  () Tj  0 g  1 0 0 1 2 355.55 Tm  0 g  (Dear test:) Tj  0 g  1 0 0 1 2 341.68 Tm  0 g  () Tj  0 g  1 0 0 1 2 327.8 Tm  0 g  (Thank you for the more random words here.  )Unfortunately, more words here) terminating (words here) Tj  

这里还有一组空括号,如下所示:

() Tj

这些表示呈现PDF时的回车符和换行符。任何帮助表示赞赏。提前谢谢。

---更新以回答以下问题

任何类型的用户输入都可以放在开括号和右括号之间。我想提取所提供的所有内容,但这可能是,即使用户忘记平衡其括号。唯一的保证是括号内的文本是用户输入,但是他们输入文本取决于它们,所以它不遵循预定义的格式,如([abbrev]:[content])等等。内容只保证在一个开放的parens,一个紧密的parens之间,并且在紧密的parens之后是字母'Tj'。

1 个答案:

答案 0 :(得分:0)

正如我在评论中提到的,我无法帮助.NET,但我可以给你一个可能有帮助的表达。我认为解决方案需要“消极前瞻”,而perl提供了这一点。问题是我没有使用perl这么久我忘记了如何让它在整个流中游行。如果我将流分成“(...)Tj”的块,每个都在它自己的行上,我的脚本将适用于你所有的例子:

$ cat pdf_data_line_by_line.txt
q  Q  /Tx BMC  q  0 0 471.34 407.34 re  W  n  BT  1 0 0 1 2 397.16 Tm  /Helv 12 Tf  0 g  (RE:  Request for Additional Information) Tj
q  Q  /Tx BMC  q  0 0 471.34 407.34 re  W  n  BT  1 0 0 1 2 397.16 Tm  /Helv 12 Tf  0 g  (RE:  Request for (Additional Information) Tj
0 g  1 0 0 1 2 383.29 Tm  0 g  (     13. Processing TT Instructions -) Audit Note 12) Tj
0 g  1 0 0 1 2 369.42 Tm  0 g  () Tj
0 g  1 0 0 1 2 355.55 Tm  0 g  (Dear test:) Tj
0 g  1 0 0 1 2 341.68 Tm  0 g  () Tj
0 g  1 0 0 1 2 327.8 Tm  0 g  (Thank you for the more random words here.  )Unfortunately, more words here) terminating (words here) Tj
$ cat get_pdf_text.pl
#!/usr/bin/perl
while (<>) {
   # find some text
   if ( /[^(]*\((?!\)).*\) Tj/ ) {
      # strip off leading junk
      s/[^(]*\((?!\))[ ]*([^)].*)\) Tj/$1/;
      # output saved part of match
      print $_;
      print "YOUR DELIMITER HERE\n";
   }
}
$ cat pdf_data_line_by_line.txt | ./get_pdf_text.pl
RE:  Request for Additional Information
YOUR DELIMITER HERE
RE:  Request for (Additional Information
YOUR DELIMITER HERE
13. Processing TT Instructions -) Audit Note 12
YOUR DELIMITER HERE
Dear test:
YOUR DELIMITER HERE
Thank you for the more random words here.  )Unfortunately, more words here) terminating (words here
YOUR DELIMITER HERE

但是,如果我将这些示例合并为一个流,则会在第一个流之后停止。我尝试在's'命令的末尾使用“g”,但它没有帮助:

$ cat pdf_data_single_stream.txt
q  Q  /Tx BMC  q  0 0 471.34 407.34 re  W  n  BT  1 0 0 1 2 397.16 Tm  /Helv 12 Tf  0 g  (RE:  Request for (Additional Information) Tj 0 g  1 0 0 1 2 383.29 Tm  0 g  (     13. Processing TT Instructions -) Audit Note 12) Tj 0 g  1 0 0 1 2 369.42 Tm  0 g  () Tj  0 g  1 0 0 1 2 355.55 Tm  0 g  (Dear test:) Tj 0 g  1 0 0 1 2 341.68 Tm  0 g  () Tj  0 g  1 0 0 1 2 327.8 Tm  0 g  (Thank you for the more random words here.  )Unfortunately, more words here) terminating (words here) Tj
$ cat pdf_data_single_stream.txt | ./get_pdf_text.pl
RE:  Request for (Additional Information) Tj 0 g  1 0 0 1 2 383.29 Tm  0 g  (     13. Processing TT Instructions -) Audit Note 12) Tj 0 g  1 0 0 1 2 369.42 Tm  0 g  () Tj  0 g  1 0 0 1 2 355.55 Tm  0 g  (Dear test:) Tj 0 g  1 0 0 1 2 341.68 Tm  0 g  () Tj  0 g  1 0 0 1 2 327.8 Tm  0 g  (Thank you for the more random words here.  )Unfortunately, more words here) terminating (words here
YOUR DELIMITER HERE

替换字符串......

s/[^(]*\((?!\))[ ]*([^)].*)\) Tj/$1/

...执行以下操作:找到零个或多个不是'(',后跟单个'('后面没有'')的字符(这是你需要负向前瞻的地方,这消除了'()Tj'个案),后跟零个或多个空格,然后记住{如果它不是')'跟随下一个字符,跟随字符零或多个},如果后跟一个')Tj',则替换所有通过记住的字符串。 如果有人可以建议(可能非常简单)让脚本一直在流中进行游戏,那么这应该可以解决手头的问题。