Чому [az] зірочка відповідає номерам?


13

У мене є 3 каталоги на поточному шляху.

$ls
a_0db_data  a_clean_0db_data  a_clean_data
$ls a_*_data
a_0db_data:

a_clean_0db_data:

a_clean_data:

$ls a_[a-z]*_data
a_clean_0db_data:

a_clean_data:

Я очікував, що остання команда ls відповідає лише a_clean_data. Чому він також відповідав тому, що містить 0?

bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)

2
Дивіться це запитання, щоб дізнатися більше про різницю між регулярним виразом і глобусом.
terdon

4
Тож факт, що a_*_dataзбігся `будь-якого з цих файлів, вас не здивував?
Cthulhu

@Cthulhu ти мене отримав!
користувач13107

Відповіді:


29

[a-z]Частина не те , що збігається з номером; це *. Можливо, ви плутаєте глобулювання оболонки та регулярні вирази .

Такі інструменти, як grepприйняття різних ароматів регулярних виразів ( базові за замовчуванням, -Eдля розширених, -Pдля регулярних виразів Perl )

Напр. ( -vПеревертає матч)

$ ls a_[a-z]*_data | grep -v "[0-9]"
a_clean_data

Якщо ви хочете скористатись bashe regex, ось приклад того, як перевірити, чи є змінною $refціле число:

re='^[0-9]+$'
if ! [[ $ref =~ $re ]] ; then
  echo "error"
fi

Як тоді використовувати bash regex? (див. tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html )
користувач13107

1
дивіться це запитання
umläute

21

Тож проблема полягає в тому, чому a_[a-z]*_dataвідповідає a_clean_0db_data?

Це можна розділити на чотири частини:

  • a_відповідає початку a_clean_0db_data, залишаючи clean_0db_dataвідповідне

  • [a-z]відповідає будь-якому символу в діапазоні a-z(наприклад c), залишаючи lean_0db_dataвідповідним

  • * відповідає будь-якій кількості символів, наприклад lean_0db

  • _data відповідає трейлінгу _data

У регулярних виразах [a-z]*буде означати будь-яку кількість символів (включаючи нуль) у діапазоні a..z , але ви маєте справу з глобулюванням оболонки, а не з регулярними виразами.

Якщо ви хочете регулярних виразів, у кількох findреалізаціях є -regexпредикат для цього:

find . -maxdepth 1 -regex "^.*/a_[a-z]*_data$"

Тут -maxdepthє лише обмеження результатів пошуку на папку, в якій ви перебуваєте. Регулярний вираз відповідає всьому імені файлу, тому я додав a, ^.*/щоб відповідати частині шляху


11

*в шаблонах оболонок відповідає 0 або більше символів. Це не слід плутати з *оператором регулярного вираження, який означає 0 або більше попереднього атома .

У *базових шаблонах оболонки немає еквівалента регулярного вираження . Однак різні оболонки мають для цього розширення.

  • kshмає *(something):

    ls a_*([a-z])_data
  • ви можете мати те ж саме в bashс shopt -s extglobабо zshз setopt kshglob:

    shopt -s extglob
    ls a_*([a-z])_data
  • В zshз extendedglobвключеними #еквівалентно регулярним виразом *:

    setopt extendedglob
    ls a_[a-z]#_data
  • В останніх версіях ksh93ви також можете використовувати регулярні вирази в глобусах. Тут із розширеними регулярними виразами:

    ls ~(E:a_[a-z]*_data)

Зауважте, що [a-z]відповідає різним речам, залежно від поточного місцеположення. Як правило , він відповідає лише 26 aна zлатинські , не акцентувати букви в Cлокалі. В інших місцевостях це, як правило, більше, і не завжди має сенс. Ви можете віддати перевагу відповідності букві у вашій місцевості [[:alpha:]].


Чи можете ви навести приклад [a-z]збігу більше того, що 26 літер збігаються в мові C? Що я пам’ятаю, коли я востаннє переглянув це, всі кодування, які практично використовуються у варіантах Unix, були базою ISO-646 (тоді верхні 128 кодів, де вони використовуються по-різному, безпосередньо для символів у кодуваннях, таких як ISO-8859-X, поєднані в кодування, такі як UTF-8 або сімейство EUC). Навіть AIX не мав локалів EBCDIC (принаймні, як мені доступно). Я пам'ятаю, намагався знайти, чи вимагали цього стандарти POSIX / UNIX, але я не пам’ятаю результату.
AProgrammer

1
@AProgrammer, що не залежить від кодування, засноване на порядку сортування (LC_COLLATE). [a-z]як правило, включає éабо í(але не обов'язково ź) в локалі, де їх має гардероб, незалежно від того, кодова точка в кодуванні знаходиться між a і z чи ні. Лише локальний код C гарантує порядок сортування на основі значення кодової точки. Дивіться цю іншу відповідь для більш детальної інформації.
Стефан Шазелас

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