AWK игнорирует регистр в классах символов

#awk

#awk

Вопрос:

Я хотел бы написать условие awk, которое соответствует строке, если она начинается с заглавной буквы. Вот пример файла данных.

 a
b
c
A
B
C
d
e
  

Допустим, я хочу сопоставить все строки, которые соответствуют символам ABC.

 awk '{ if ($1 ~ /^[ABC]/) print }' test 
A
B
C
  

Достаточно просто. Но это не сработает, если я использую символьный класс. Регистр игнорируется.

 awk '{ if ($1 ~ /^[A-C]/) print }' test 
b
c
A
B
C
  

Интересно, что это работает:

 awk '{ if ($0 ~ /^[[:upper:]]/) print }' < test
A
B
C
  

Из документации я бы ожидал, что команда будет:

 awk '{ if ($0 ~ /^[:upper:]/) print }' < test
  

Что я неправильно понимаю? В частности, почему [A-C] регистр не чувствителен и почему мне нужно писать [[:upper:]] вместо [:upper:] ?

 echo $LANG
en_US.utf8
  

Комментарии:

1. Я не вижу ваших результатов. Что содержит ваша LANG переменная окружения?

2. Со страницы руководства gawk: символьный класс допустим только в регулярном выражении внутри скобок списка символов.

3. Возможно, я понимаю, о чем вы говорите. Мне нужно [[A-C]] ? awk '{ if ($0 ~ /^[[A-C]]/) print }' test выдает 0 результатов. То же самое для gawk.

4. нет. предположим, вы хотите выполнить поиск шестнадцатеричной цифры, можно сказать, /[[:digit:]a-fA-F]/ — так что [:character_class:] находится внутри внешнего [brackets] , как обычные символы

5. Понял, я был сбит с толку, потому что иногда [A-C] упоминается как символьный класс (т. е. download.oracle.com/javase/tutorial/essential/regex /… и некоторых версиях man awk ), но не в man gawk !

Ответ №1:

Что я неправильно понимаю? В частности, почему [A-C] не чувствителен к регистру

Вероятно, это связано с вашим языком, который может повлиять на диапазоны классов символов.

Попробуйте установить, export LC_ALL=C а затем снова запустить свою awk команду с [A-C]

почему мне нужно писать [[:upper:]] вместо [:upper:]?

[:upper:] по сути, это способ записи диапазона A-Z без учета локали, но вы также хотите, чтобы это был символьный класс, поэтому вы переносите его в [] , следовательно [[:upper:]] . Так, например, если бы вы хотели сопоставить все символы верхнего регистра и цифры, вы бы написали [[:upper:][:digit:]]

Комментарии:

1. Это имеет прекрасный смысл (re: [:upper:]), но можете ли вы объяснить, почему awk '{ if ($0 ~ /^[:upper:]/) print }' < test возвращает только e ??

2. Да, это была локальная проблема. export LC_ALL=C представил ожидаемый результат. Спасибо за совет!

3. @schmid, это [:upper:] точно то же самое, что и это [epru:] — скобки содержат набор символов, которые вы хотите сопоставить.