Узгодження рядка з фіксованою кількістю символів за допомогою grep


9

Я намагаюся знайти всі 6буквені слова за допомогою grep. У мене зараз це:

grep "^.\{6\}$" myfile.txt 

Однак я знаходжу, що я також отримую такі результати, як: étuis, étude.

Я підозрюю, що це має щось спільне із символами вище eу наведених словах.

Чи можу я щось зробити, щоб цього не сталося?

Спасибі за вашу допомогу!

Відповіді:


4

grepІдея персонажа залежить від локальної залежності . Якщо ви перебуваєте в не-Unicode-локалі та збираєте файл із символів Unicode, кількість підрахунків символів не збігається. Якщо echo $LANGтоді ви побачите локал, в якому ви перебуваєте.

Якщо ви встановите LC_CTYPEі / або LANGзмінні середовища значення, що закінчується на ".UTF-8", ви отримаєте правильну поведінку:

$ cat data
étuis
letter
éééééé
$ LANG=C grep -E '^.{6}$' data
étuis
letter
$ LANG=en_US.UTF_8 grep -E '^.{6}$' data
letter
éééééé
$

Ви можете змінити локаль лише для однієї команди, призначивши змінну в тому ж рядку, що і команда.

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


Зауважте, що все-таки можна зламати речі або принаймні не робити саме те, що ви очікуєте, за наявності поєднання символів . Ви grepможете ставитися до ЛАТИННОГО МАЛЬКОГО ПІСЛЕННЯ E + КОМБІНУВАННЯ ХАРАКТЕРУ ГОСТРУЙТЕ ВІД ІНШОМУ, ніж ЛАТИННИЙ МАЛИЙ ПІСЛЕННЯ Е З Гострою.


якщо ви користуєтеся ., щось подібне wăsd'sвідповідатиме
cuonglm

'- це символ, який розумно може бути частиною "рядка з фіксованою кількістю символів".
Майкл Гомер

Можливо. І вам слід встановити і те, LC_CTYPEі LANGінше, як щось LC_CTYPE=en_US.UTF-8 LANG=en_USне вдасться. Використовуйте LC_ALLдля безпеки.
cuonglm

2

Спробуйте це:

LC_ALL=C.UTF-8 grep -x '[_[:alnum:]]\{6\}' file

-xвикористовувати для узгодження цілого рядка та визначається POSIX (див. греп ).

Дивіться тут для хорошого пояснення того, що LC_ALLробить. Ви можете встановити LANGабо LC_CTYPEвикористовувати utf-8, щоб отримати таку саму поведінку. Афект прийому замовлення LC_ALL= LANG= = => LC_CTYPE.


2

З GNU, grepколи він створений за допомогою підтримки PCRE, ви можете:

grep -Px '\X{6}'

Хоча .відповідає персонажу, \Xвідповідає ідеограмі / графемі.

У мові UTF-8:

$ locale charmap
UTF-8
$ printf '\u00e9tuis\n\u00e9tudes\n' | grep -Px '\X{6}'
études
$ printf 'e\u0301tuis\ne\u0301tudes\n' | grep -Px '\X{6}'
études

В цьому останньому étudesє 7 символів, 8 байтів і 6 графем.


Здається, не працює: echo épée | grep -Px '\X{6}'ouputépée
cuonglm

@Gnouc, вам потрібно запустити це в локалі UTF-8 (якщо éвищевказані були закодовані в UTF-8).
Стефан Шазелас

О, мої помилки. Він працює з UTF-8.
cuonglm

0

Ви можете спробувати щось на кшталт:

grep "^[A-Za-z]\{6\}$" myfile.txt

або якщо слова можуть містити і цифри, тоді:

grep "^[A-Za-z0-9]\{6\}$" myfile.txt

Просто додайте будь-які символи до квадратних дужок, які ви хочете окрім цих.


Це зовсім не буде відповідати étude, оскільки символ ASCII, що відповідає акценту, зіпсує регулярний вираз.
Олексій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.