2017-02-17 10 views
0

Мне нужно вытащить текст из потока PDF в виде строки. Этот поток будет содержать как разметку для описания внешнего вида текста, так и самого текста. Строка, которую я получаю, чтобы мое регулярное выражение должно было работать, никогда не будет содержать никаких возвратов каретки или строк. Области текста, которые меня интересуют, всегда будут внутри скобок (и там, возможно, будут скобки в скобках), а после окончательной скобки будут буквы «Tj». Короче, что я после всегда будет следовать соглашению:regex, где скобки могут быть не сбалансированы

(.....) Tj 

В настоящее время регулярное выражение у меня работает, до тех пор, как круглые скобки все сбалансировано:

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

Однако если сам текст содержит несбалансированный паретез, это регулярное выражение не будет тянуть то, что я хочу, и я не уверен, как изменить его, чтобы иметь возможность обрабатывать несбалансированные скобки.

Вот пример того, что будет считаться «нормальным» строка:

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. Любая помощь приветствуется. Заранее спасибо.

--- ОБНОВЛЕНИЕ, чтобы ответить на следующие вопросы

Любого типа пользовательского ввода может быть размещен между открытой и закрывающей скобкой. Я хочу извлечь весь контент, как это было предусмотрено, хотя это может быть, даже если пользователь забыл сбалансировать свою скобку. Единственная гарантия заключается в том, что текст между скобками вводится пользователем, но, тем не менее, они вводят текст до них, поэтому он НЕ следует предопределенному формату, например ([аббревиатура]: [контент]) и т. Д. контент гарантированно будет только между открытыми parens, близкими parens, а после закрытия parens будут буквы Tj.

+0

Выражения Regualr не могут обрабатывать произвольно вложенные круглые скобки. Язык совпадающих скобок сам по себе не является регулярным. – CollinD

+0

Я не понял ваше регулярное выражение, однако, я играл с вашими примерами, и я думаю, что это выполнимо, хотя вам, возможно, придется сделать несколько поисков и заменить. В примере «(RE: Request for (Дополнительная информация)» вы можете извлечь «RE: Request for (Дополнительная информация)», заменив начало строки, за которой следует любое количество символов любого другого, кроме открытой круглой скобки, затем выполните пронумерованные save. Ключ в том, что. * получает БОЛЬШОЙ матч, поэтому он обходит первую открытую скобку (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 

Однако, если я объединить примеры в единый поток , он останавливается после первого. Я попытался с помощью "г" в конце команды '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/ 

...делает следующее: найдите ноль или более символов, которые НЕ '(', а затем один '(', за которым следует NOT ')' (здесь вам нужен отрицательный просмотр, и это исключает случаи '() Tj'), за которым следуют ноль или более пробелов, а затем помните {один следующий символ, если он не является) и ноль или несколько следующих символов}, если за ним следует ') Tj', и замените все это на запоминаемую строку. Если кто-нибудь может предложить (возможно, очень простой) способ заставить скрипт пройти весь путь через поток, то это должно решить проблему.

+0

Благодарим вас за сообщение. Это сработало, как только вы разделились на «Tj», чтобы все было в линии, как вы это делали выше. – resu