2017-02-17 81 views
0

我必須從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:要求提供補充資料」出這一點。

,這裏是一個例子情況下,我的正則表達式將在失敗(我已經添加了不平衡括號):

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呈現時的回車和換行符。任何幫助表示讚賞。先謝謝你。

--- UPDATE來回答以下

問題的任何類型的用戶輸入可以被放置在打開和關閉括號之間。我想提取所有提供的內容,但可能是,即使用戶忘記平衡括號。唯一的保證是圓括號之間的文本是用戶輸入,但是他們輸入的文本取決於它們,所以它不遵循預定義的格式,如([abbrev]:[content])等。內容只能保證在一個開放的父親和一個親密的父親之間,並且在親密的父親之後將是字母'Tj'。

+0

Regualr表達式不能處理任意嵌套的括號。匹配括號的語言本身是不規則的。 – CollinD

+0

我還沒有想出你的正則表達式,但是,我已經玩過你的例子了,我認爲這是可行的,儘管你可能需要做一個以上的搜索和替換。在例子「(RE:請求(附加信息)」)中,可以提取「RE:請求(附加信息)」,通過替換行的開頭,後面跟任何數字的任何字符,而不是左括號,然後進行編號保存,關鍵在於:*得到最長的匹配,所以它將繞過第一個左括號(RE:...並一直走到(另外...我明天再看看這個 –

+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 

但是,如果我結合實例成一個單一的數據流,它會在第一個之後停止。我試着用 「G」 在 'S' 命令的結束,但它並沒有幫助:

$ 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',請記住{後面的一個字符},並用記憶的字符串替換所有的字符。 如果任何人都可以建議(可能非常簡單)的方式來讓腳本在整個流中游行,那麼這應該可以解決手頭的問題。

+0

感謝您發佈您的答案。它起作用了,一旦你將'Tj'分割成一行,就像你上面所做的那樣。 – resu