Как понять этот вывод Sed на ОС MA C? - PullRequest
0 голосов
/ 01 мая 2020

Команда:

echo "aabb" |sed -n -E "s/([a-z])/\1/p"

Выходы:

aabb

Команда:

echo "aabb" |sed -n -E "s/([a-z])([a-z])/\1/p"

Выходы:

abb

Команда:

echo "aabb" |sed -n -E "s/([a-z])([a-z])/\1 \2/p"

Выходы:

a abb

Выше меня смутили 3 выхода.

Насколько я понимаю:

  • 1-й должен быть a ;
  • 2-е должно быть a ;
  • 3-е должно быть aa .

Но фактический результат не соответствует ожиданиям. Почему?

Ответы [ 2 ]

1 голос
/ 01 мая 2020

Но фактический результат не соответствует ожиданиям. Почему?

Мне кажется, вы ожидаете, что регулярное выражение заменит всю строку. Это не так. Он заменяет только согласованную часть, ту часть ввода, которая была сопоставлена ​​с регулярным выражением. И только эта часть заменяется.

Так, например:

echo "aabb" |sed -n -E "s/([a-z])([a-z])/\1 \2/p"

Соответствует регулярному выражению:

aabb
^^       - those two characters are the _first_ match against ([a-z])([a-z])
^        - saved in \1
 ^       - saved in \2
^^ only this part is replaced by `\1 \2` which results in:
a abb
^^^   the replacement `\1 \2`
   ^^ the rest of the input is left untouched

Тогда только соответствующая часть ввода заменяется на строка замены . Таким образом, часть aa заменяется на \1 \2. Часть строки до или после регулярного выражения остается нетронутой.

1 голос
/ 01 мая 2020

ИМХО, это потому, что ваше регулярное выражение не завершено, вам нужно дать .* в вашем регулярном выражении, например:

echo "aabb" |sed -n -E "s/([a-z]).*/\1/p"

Делая это, мы точно перехватываем один символ и затем сопоставляем остальную часть строки так, следовательно, он печатает нормально.

, почему не работает одиночный [a-z]: потому что он ищет только один символ в строке, а когда регулярное выражение не совпадает ни с чем, вся строка попадает в \1 временной буфер, следовательно, его печать вся строка.

Давайте рассмотрим пример, в котором строка имеет только 1 символ, тогда регулярное выражение OP будет работать, например ->

echo "a" |sed -n -E "s/([a-z])/\1/p"

ПРИМЕЧАНИЕ: Также вы можете удалить -n и /p часть в вашей команде и можете использовать как:

echo "aabb" |sed -E "s/([a-z]).*/\1/"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...