2015-03-03 6 views
1

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

В моем файле.txt я хотел бы совместить с командами «grep» и «sed» только текст внутри »(« и »)». Пример:

This is my line and (this is the text to match!), and bla bla bla... 

Но некоторые линии могут выглядеть следующим образом:

Another line (text to match 1;) something else, (text to match 2) 

Здесь проблемы:
Выражение типа
grep '(.*)' file.txt или sed 's/(.*)//' <file.txt
не будет работать, потому что .* по умолчанию жадного. Это означает, что он будет соответствовать второй пример, как это:
Другая линия (текст, чтобы соответствовать 1;) что-то другое, (текст, чтобы соответствовать 2)

решения должны быть нежадным согласование, то Я попытался использовать нежирный квантор ?.

grep -E '\(.*?\)' file.txt 

или с СЭД

sed -r 's/\(.*\)//' <file.txt 

В этом случае мы должны использовать -E и -r сделать Grep и SED прочитать расширенные выражения, и мы также должны использовать \ перед тем (.
Но даже это решение, похоже, не работает, я не знаю почему.
Тогда я попытался что-то вроде:

grep '(.*)[^(]*' file.txt 

для того, чтобы найти строки, содержащие только один «(текст, чтобы соответствовать)» и, если я хотел бы, например, чтобы переписать текст внутри(), синтаксис будет:

sed 's/(.*)\([^(]*\)/(new text)\1/'<file.txt 

Но пока это похоже на работу, я обнаружил, что '(.*)[^(]*' матча некоторые линии, как старый (.*) (это мистерия ...)

Все лучшее решение ?

Заранее спасибо

+0

Для того, чтобы помочь вам, '' (. *) [^ (] * '' Совпадает с '(. *)', Потому что первый жадно сопоставляет все, что может, прежде чем перейти к следующему, и поскольку следующий также имеет квантор asterisk, он соответствует 0 раз, потому что '. *' соответствует всем. Кроме того, отличная работа, объясняющая, что вы пробовали. Добро пожаловать в StackOverflow! –

+1

Спасибо за ответ. Я понимаю, что вы имеете в виду , Я думал, что '[^ (] *' точно остановится, когда он встретит '(', но на самом деле он никогда не встретится с ним, потому что '. *' соответствует уже всем этим. – TTK

+0

Да, точно! Хорошая работа :) –

ответ

1

это регулярное выражение должно работать:

\(([^\)]+)\)/g 

как вы можете видеть здесь, это работает:

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

+0

Спасибо , он работает. (даже простой '' \ ([^ \)] * \) '' хорош) – TTK

+0

Рад, что он работает. Примите мой ответ, выбрав галочку рядом с моим ответом – adrCoder

1

Использование гну AWK это довольно легко:

s='Another line (text to match 1;) something else, (text to match 2)' 

awk 'BEGIN{ FPAT="\\([^)]*\\)" } {for (i=1; i<=NF; i++) print $i}' <<< "$s" 
(text to match 1;) 
(text to match 2) 
+0

Это может понадобиться 'gnu awk' из-за' FPAT' – Jotne

+1

Да, я четко упомянул 'gnu awk' в своем ответе. – anubhava

1

Все, что вам нужно:

$ cat file 
Another line (text to match 1;) something else, (text to match 2) 

$ sed 's/(\([^)]*\)/(foo/' file 
Another line (foo) something else, (text to match 2) 

$ sed 's/(\([^)]*\)/(foo/2' file 
Another line (text to match 1;) something else, (foo) 

$ sed 's/(\([^)]*\)/(foo/g' file 
Another line (foo) something else, (foo) 

Не-жадный квантор ? никогда не требуется и редко используется достаточно, чтобы гарантировать, насколько труднее это делает ваш регэкспы читать/понимать. Он также не поддерживается всеми инструментами. При отладке «жадных» проблем совпадения всегда начинайте с изменения .*, если присутствует, до [^x]*, где x - это любой персонаж, который появляется сразу после интересующей вас строки, ) в этом случае.

+1

Спасибо, это работает. – TTK

 Смежные вопросы

  • Нет связанных вопросов^_^