Как сделать grep [AZ] независимым от локали? - PullRequest
7 голосов
/ 23 июля 2011

Я делал некоторые ежедневные расчеты и внезапно обнаружил, что что-то вроде тривиального не работает:

$ echo T | grep [A-Z]

Нет совпадений.

Почему T не находится в диапазоне AZ?

Я немного изменил регулярное выражение:

$ echo T | grep [A-Y]

Совпадение!

Вау!Как T в AY, но не в AZ?

Очевидно, это потому, что мое окружение настроено на эстонский язык, где Y находится в конце алфавита, а Z где-то посередине: ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY

$ echo $LANG
et_EE.UTF-8

Все это стало для меня шоком.99% времени я использую компьютерный код, а не эстонскую литературу.Я все время использовал grep неправильно?Какие ошибки я совершил из-за этого в прошлом?

После нескольких попыток я нашел следующее решение:

$ echo T | LANG=C grep [A-Z]

Это рекомендуемый способсделать grep независимым от локали?

Далее больше ... было бы безопасно определить псевдоним так:

$ alias grep="LANG=C grep"

PS. I 'Мне также интересно, почему диапазоны символов, такие как [A-Z] локаль, зависят в первую очередь, в то время как \w, кажется, не зависят от локали (хотя в руководстве сказано, что \w эквивалентно [[:alnum:]] - но я выяснил, что последнеезависит от локали, а \w - нет).

1 Ответ

5 голосов
/ 23 июля 2011

Регулярные выражения POSIX, которые Linux и FreeBSD grep поддерживают естественным образом, а некоторые другие поддерживают по запросу, содержат серию шаблонов [: xxx:], которые учитывают локали. Для получения дополнительной информации см. Справочную страницу.

   grep '[[:upper:]]' 

Поскольку [] являются частью имени шаблона, вам также необходим внешний [], независимо от того, как странно он выглядит.

С появлением этих кодов: классические \ w и т. Д. Остаются строго в языке C. Таким образом, ваш выбор шаблонов определяет, использует ли grep текущую локаль или нет.

[A-Z] должно следовать за локалью, но вам может потребоваться установить LC_ALL, а не LANG, особенно если система устанавливает для LC_ALL другое значение для вас.

...