Як використовувати [\ w] + у регулярному вираженні в sed?


24

Я в Windows, але, мабуть, моє запитання тут все-таки правильно розміщено.

C:\Users\User>grep --version
GNU grep 2.6.3

C:\Users\User>sed --version
GNU sed version 4.2.1

Я помітив, що такі роботи (вихідні here):

echo here | grep -E "\w+"
echo here | grep -E "[her]+"

Але це не працює (нічого не виходить):

echo here | grep -E "[\w]+"

Це знову робить (виведення here):

echo here | grep -P "[\w]+"

Отож, [\w]є певним для регулярних виразів Perl, я припускаю. Це правильно?

Отже, давайте поговоримо sed. Це працює (виведення gone):

echo here | sed -r "s/\w+/gone/"
echo here | sed -r "s/[her]+/gone/"

І знову це не так (виведення here):

echo here | sed -r "s/[\w]+/gone/"

Тепер, як я можу активувати Perl регулярні вирази для sed - чи є спосіб?

Відповіді:


11

Різні інструменти та їх версії підтримують різні варіанти регулярних виразів. Документація кожного з них розповість, що вони підтримують.

Стандарти існують, щоб можна було покластися на мінімальний набір функцій, доступний у всіх відповідних програмах.

Наприклад, всі сучасні реалізації sedта grepреалізація основних регулярних виразів, визначених POSIX (принаймні одна версія чи інша версія стандарту, але цей стандарт не розвинувся в цьому відношенні за останні кілька десятиліть).

У POSIX BRE та ERE у вас є [:alnum:]клас символів. Це відповідає буквам і цифрам у вашій мові (зверніть увагу, що часто включає набагато більше, ніж, a-zA-Z0-9якщо локаль не C).

Так:

grep -x '[[:alnum:]_]\{1,\}'

відповідає одній або більше alnum або _.

[\w]вимагає POSIX, щоб відповідати або зворотній косій лінії, або w. Таким чином, ви не знайдете grepабо sedвтілення, де це доступно (якщо тільки не з нестандартними параметрами).

Поведінка \wокремо не визначена POSIX, тому реалізаціям дозволяється робити те, що вони хочуть. ГНУ grepдодав, що це давно.

У GNU grepраніше існував власний механізм regexp, однак тепер він використовується libc GNU (хоча він вбудовує власну копію).

Це покликане відповідати випускникам та підкресленням у вашій місцевості. Однак, в даний момент помилка в тому, що вона відповідає лише однобайтовим символам (наприклад, не é в локалі UTF-8, хоча це явно буквою, і хоча вона відповідає é у всіх локалях, де é є одиничним персонаж).

Існує також \wоператор regexp в perl regexp і в PCRE. PCRE / perl не є регулярними виразами POSIX, вони взагалі просто інша річ.

Тепер, з тим, як GNU grep -Pвикористовує PCRE, у нього виходить та сама проблема, що і без -P. Це можна вирішити там, хоча за допомогою (*UCP)(хоча це також має побічні ефекти в не-UTF8-локалях).

GNU sedтакож використовує регекси GNU libc для власних регулярних виразів. Він використовує його таким чином, хоча він не має тієї ж помилки, як GNU grep.

GNU sedне підтримує PCRE. У кодексі є деякі докази того, що він робився раніше, але, здається, це вже не стоїть на порядку денному.

Якщо ви хочете регулярних виразів Perl, просто використовуйте, perlхоча.

Інакше я б сказав, що замість того, щоб намагатися покладатися на хибну нестандартну особливість вашої конкретної реалізації sed/ grep, було б краще дотримуватися стандарту та використовувати [_[:alnum:]].


[_[:alnum:]]це хороший спосіб вирішення, який дозволяє мені розширити його так само [\w/]( [_[:alnum:]/]у такому випадку).
бер

1
Ця відповідь застаріла щодо обмежень ВНУ grep.
Стефан Шазелас

7

Ви праві - \wце частина сумісних регулярних виразів PCRE. Однак це не є частиною «стандартного» регулярного виразів. http://www.regular-expressions.info/posix.html

Деякі версії програми sedможуть підтримувати його, але я пропоную найпростіший спосіб - просто використовувати perlв sedрежимі, вказавши -pпрапор. (Поряд із -e). (Детальніше в perlrun)

Але вам []у цьому прикладі не потрібно - це для груп дійсних речей.

echo here  | perl -pe 's/\w+/gone/'

Або в Windows:

C:\>echo here  | perl -pe "s/\w+/gone/"
gone
C:\>echo here  | perl -pe "s/[\w\/]+/gone/"
gone

Докладніше perlreпро матеріали PCRE.

Перл можна отримати тут: http://www.activestate.com/activeperl/downloads


Будь ласка , зверніть увагу на різницю між \wі [\w]в моєму питанні. Я оновлю його виходами кожної команди, щоб зрозуміти, яка з них працює, а яка - ні. Зокрема, sedрозуміє \w, але ні [\w]. Також мені потрібно [\w]працювати, тому що я хочу використовувати, [\w/]наприклад.
бер

У такому випадку це, мабуть, проблема котирування. У будь-якому випадку - це perlможна зробити :).
Sobrique

Спасибі! Відповідь Стефана Шазеласа трохи ближче до того, про що я попросив (оскільки у мене не встановлено perl - ду * b користувача Windows, я думаю), тому я прийняв його відповідь.
бер

Це нормально - але я б рекомендував встановити Perl на Windows. Це одне з перших речей, яке продовжується у мене, і я вважаю це надзвичайно корисним.
Sobrique

\wбув у GNU grep (у 80-х роках) до того, як був у perl та у GNU emacs, мабуть, ще до цього.
Стефан Шазелас

1

Я підозрюю, що grepі sedвирішують по-різному, коли застосовувати []та коли розширювати \w. У регулярному вираженні perl \wозначає будь-який символ слова та []визначте групу, яка застосовує будь-який із символів у відповідності. Якщо ви «розширити» \wдо []це буде символ клас всіх символів слова. Якщо замість цього ви зробите []спочатку, у вас буде клас символів з двома символами, \і wвін би відповідав будь-якому шаблону, що містить один або більше цих двох символів.

Отже, здається, що sedбачити []та вважати, що він містить точні символи, що відповідають, а не шанувати особливу послідовність \wяк perlі grepробити. Звичайно, []це абсолютно непотрібні в цьому прикладі, але, можливо, можна уявити випадки, коли це було б важливо, але тоді ви могли б змусити його працювати з паренами та орсами.


Я був би здивований, якби це було так. \ це код евакуації, і ви використовуєте його для виходу з роздільників. Це по суті означає, що він повинен мати вищий пріоритет, ніж будь-яка інша річ. Я думаю, що це більше ймовірно, що він не реалізований, тому що \wне є частиною специфіки регулярного вираження
Sobrique

Що ж, емпірично, здається, що це стосується використання гну sed для мене: echo whe\\ere | sed -r 's/[\w]+/gone/gдає мені gonehegoneereтак, ніби він відповідає кожному з ` and w` і робить заміну
Ерік Реноф

Я можу підтвердити те, що бачить Ерік Реноф. Отже, ми хочемо якось відхилити відхилення відкосу? :)
бер

Я не думаю, що це правильна відповідь. Sed просто не підтримує змішування різних типів визначень класів символів, тому відповідь, якщо ви повинні використовувати обидва типи класів символів, вибрати інший інструмент, або якщо ви вибираєте sed, використовуйте синтаксис, який він підтримує
Ерік Реноф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.