Чому '[az] *' відповідає неабетним рядкам?


9

У мене є файл alphanumіз цими двома рядками:

123 abc
this is a line

Мене бентежить, чому під час запуску sed 's/[a-z]*/SUB/' alphanumя отримую такий результат:

SUB123 abc
SUB is a line

Я очікував:

123 SUB
SUB is a line

Я знайшов виправлення (використовуйте sed 's/[a-z][a-z]*/SUB/'замість цього), але не розумію, чому він працює, а мій - ні.

Ви можете допомогти?



@Kamaraj, цей схожий, але має схему оболонки проти регулярного вираження плутанини зверху (а відповіді концентруються на першому, оскільки саме ls foo*там використовується). Але в будь-якому випадку, якщо ви знайдете запитання, які є дублікатами, я думаю, ви повинні також мати змогу позначити їх як такі.
ilkkachu

огляньте regexr.com на живу візуальність та пояснення
RozzA

@RozzA Зауважте, що веб-сайт, на який ви посилаєтесь, підтримує регулярні вирази Javascript та Perl, а не регулярні вирази POSIX.
Кусалаланда

Відповіді:


28

Шаблон [a-z]*відповідає нулю або більше символів у діапазоні aдо z( фактичні символи залежать від поточного локалу). На самому початку рядка є нульові символи 123 abc(тобто узор збігається), а також чотири з них на початку this is a line.

Якщо вам потрібна хоча б одна відповідність, то використовуйте [a-z][a-z]*або [a-z]\{1,\}, або увімкніть розширені регулярні вирази з sed -Eі використовуйте [a-z]+.

Щоб візуалізувати відповідність шаблону, додайте круглі дужки навколо кожного збігу:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

Або, щоб побачити всі матчі на рядках:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Порівняйте останній результат із

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)

7
Технічно [a-z]відповідає збіжним елементам, які можуть бути виконані більше ніж одним символом. Наприклад, у деяких угорських місцях [a-z]dzs
1818

12

Тому що *відповідає нулю або більше повторень попереднього атома, і всі двигуни регулярного випробування намагаються знайти першу відповідність. На початку рядка є підрядка з рівно нульовими літерами, тож там вона відповідає. У випадку, коли рядок починається з літери, *збігається стільки, скільки може, але це є другорядним для пошуку крайнього лівого збігу.

Сірники нульової довжини можуть бути дещо проблематичними, і як ви бачили, рішення полягає в тому, щоб змінити візерунок таким чином, щоб він вимагав принаймні одного символу. З розширеними реджексами ви можете +для цього:sed -E 's/[a-z]+/SUB/'

Для задоволення спробуйте:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.