2016-08-13 4 views
0

Почему эта простая замена sed внутри bash не работает?Простая замена с sed внутри bash не работает

echo '[a](!)' | sed 's/[a](!)/[a]/' 

возвращает [a](!) вместо [a]. Но почему, учитывая, что только three characters необходимо экранировать в заменяющей строке sed?

Если я объяснить для случая, когда нужно заменить в строке регулярного выражения и попытаться

echo '[a](!)' | sed 's/\[a\]\(!\)/[a]/' 

она до сих пор не работает дополнительных символов.

ответ

1

СЭД использует Brès по умолчанию и EREs может быть разрешен путем побега отдельного metacharaters ERE или используя аргумент -E. [ и ] являются метасимволами BRE, ( и ) являются метасимволами ERE. Когда Вы писали:

echo '[a](!)' | sed 's/\[a\]\(!\)/[a]/' 

вы переворачивая [ и ] BRE метасимволов в литералы, что хорошо, но вы поворачивались буквальный ( и ) в ЭРД метасимволы, что плохо. Это то, что вы пытаетесь сделать:

echo '[a](!)' | sed 's/\[a\](!)/[a]/' 

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

echo '[a](!)' | sed 's/\(\[a\]\)(!)/\1/' 

, чтобы избежать дублирования [a] с обеих сторон замещения. При включенном EREs используя -E аргумент, который длиться будет:

echo '[a](!)' | sed -E 's/(\[a\])\(!\)/\1/' 

Прочитайте SED страницу человека и регулярное выражение учебник.

+0

Я не вижу смысла в захвате * * известный образец часть для использования в замене, то есть избыточные накладные расходы. –

+0

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

3

Дело в том, что [a] в шаблоне регулярных выражений не соответствует квадратным скобкам, которые образуют выражение скобки . Побег первого [ для того, чтобы быть проанализировано как буквальное [ символа, и ваша замена будет работать:

echo '[a](!)' | sed 's/\[a](!)/[a]/' 
         ^^ 

См this demo

-1

man echo сообщает, что команда echo отображает строку текста. Итак, [ и ( с их закрывающими скобками - это всего лишь текст.

Если вы читаете man grep и введите там /^\ *Character Classes and Bracket Expressions и /^\ *Basic vs Extended Regular Expressions, вы можете прочитать разницу. sed и другие инструменты, которые используют regex, интерпретируют это как классы символов и выражения скобок.

Вы можете попробовать это

$ echo '[a](!)' | sed 's/(!)//' 
+0

Нет, я просто прочитал это на страницах руководства, чтобы дать ответ с ответами и нашел это решение самостоятельно. Я просто попытался дать ответ вместо голосования. Было бы неплохо, если бы участники опроса могли только проголосовать. Но, может быть, это не шутка, что люди говорят о Джоне Ските. –

+0

Нет, я прочитал эту страницу, искал ответ на страницах руководства, что я всегда делаю и написал свой ответ. Иногда некоторые люди быстрее, иногда люди не согласны с этим и любят это говорить. Некоторые люди думают, что есть плохие вопросы, некоторые думают, что есть плохие ответы, а некоторые думают, что каждая помощь приветствуется, но некоторые не думают так. Если бы вы могли объяснить, что не так с моим ответом и почему этот ответ не работает в некоторых версиях оболочки или разных версиях sed или не переносится, я мог бы принять ваше голосование, потому что я чему-то научился, но вы не знаете, дайте подсказку. –

+0

Какие страницы руководства, которые вы рекомендуете, указывают на разницу в символах, которые используются как литералы и метасимволы в разных формах, и что это зависит от используемых инструментов? Дайте мне информацию, которая просветит меня и перестанет говорить, что вам что-то не нравится. –

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