Сед звездный групповой матч не жадный без разбега? - PullRequest
0 голосов
/ 28 апреля 2018

Я хотел бы заменить любое количество букв a или b (на самом деле, более длинные строки, поэтому классы символов не подойдут), но очевидная вещь терпит неудачу:

$ echo xab |  sed -E 's/(a|b)*//'
xab
$ echo xab | sed 's/\(a\|b\)*//'
xab

Я бы ожидал, что каждый из них будет выводить только 'x'. И с квантификатором + вместо квантификатора * вот что происходит.

Почему * не жаден здесь, и какой лучший подход к этому?

Один обходной путь - сначала соответствовать всему; например

$ echo xq-as | sed -E 's/(foo|bar|xq)(-as|-gh|-ts)*/\1/'
xq

, но сделать этот начальный матч - сложная задача.

Это похоже на то, что для соответствия двигателя RE требуется что-то без звездочки, чтобы согреть его.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Ваш RegEx соответствует началу строки, где звездочка соответствует нулю вхождений группы захвата.

См. Разницу (используйте точку для визуализации матча)

$ echo xab | sed -E 's/(a|b)*//'
xab
$ echo xab | sed -E 's/(a|b)*//g'
x
$ echo xab | sed -E 's/(a|b)*/./'
.xab
$ echo xab | sed -E 's/(a|b)*/./g'
.x.
0 голосов
/ 28 апреля 2018

Используйте модификатор g для замены каждого совпадения.

echo xab |  sed -E 's/(a|b)*//g'

Без этого он заменяет только первый матч. И поскольку * соответствует 0 вхождениям, оно соответствует строке нулевой длины перед x.

Вы можете увидеть это, если сделаете:

echo xab | sed -E 's/(a|b)*/FOO/'

результат

FOOxab

Другое решение заключается в использовании + вместо *, поэтому для него требуется совпадение не менее 1 символа.

echo xab |  sed -E 's/(a|b)+//'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...