У меня есть 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)
bash
regular-expression
wildcards
user13107
источник
источник
a_*_data
совпадение с любым из этих файлов вас не удивило?Ответы:
[a-z]
Часть не то , что совпадает с номером; это*
. Вы можете быть запутанной оболочка подстановки и регулярные выражения .Такие инструменты, как
grep
принимают различные разновидности регулярных выражений ( базовые по умолчанию,-E
расширенные,-P
для регулярных выражений Perl )Например, (
-v
инвертирует совпадение)Если вы хотите использовать регулярное выражение bash, вот пример того, как проверить, является ли переменная
$ref
целым числом:источник
Итак, проблема в том, почему
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
предикат для этого:-maxdepth
Только здесь , чтобы ограничить поиск-результаты в папку находятся. Регулярное выражение соответствует всему файлу, поэтому я добавил ,^.*/
чтобы соответствовать путям-частиисточник
*
в шаблонах оболочки соответствует 0 или более символов. Это не должно быть перепутано с*
оператором регулярного выражения, который означает 0 или больше предшествующего атома .В
*
базовых шаблонах оболочки нет эквивалента регулярному выражению . Тем не менее, различные оболочки имеют расширения для этого.ksh
имеет*(something)
:Вы можете иметь то же самое
bash
сshopt -s extglob
илиzsh
сsetopt kshglob
:В
zsh
сextendedglob
включен,#
эквивалентно регулярному выражению*
:В последних версиях
ksh93
вы также можете использовать регулярные выражения в глобах. Вот с расширенными регулярными выражениями:Обратите внимание, что это
[a-z]
соответствует разным вещам в зависимости от текущей локали. Как правило , он соответствует только 26a
наz
латинские , не акцентированные буквы вC
локали. В других регионах оно обычно соответствует большему количеству и не всегда имеет смысл. Чтобы соответствовать букве в вашем регионе, вы можете предпочесть[[:alpha:]]
.источник
[a-z]
сопоставления больше, чем 26 букв в языке C? Что я помню, когда в последний раз смотрел на это, все кодировки, практически используемые в вариантах Unix, имели ISO-646 в качестве основы (тогда верхние 128 кодов использовались по-разному, непосредственно для символов в кодировках, таких как ISO-8859-X, объединенных в кодировки, такие как UTF-8 или семейство EUC). Даже в AIX не было локалей EBCDIC (по крайней мере, так, как мне доступно). Я помню, как пытался выяснить, требовали ли этого стандарты POSIX / UNIX, но я не помню результат.[a-z]
обычно включаетé
илиí
(но не обязательноź
) в локали, где есть кодировка, независимо от того, находится ли кодовая точка в этой кодировке между a и z или нет. Только язык C гарантирует порядок сортировки на основе значения кодовой точки. Смотрите этот другой ответ для более подробной информации.