Я хотел бы спросить:
Почему echo {1,2,3}расширен до 1 2 3, что является ожидаемым поведением, а echo [[:digit:]]возвращается, [[:digit:]]пока я ожидал, что он будет печатать все цифры от 0до 9?
Я хотел бы спросить:
Почему echo {1,2,3}расширен до 1 2 3, что является ожидаемым поведением, а echo [[:digit:]]возвращается, [[:digit:]]пока я ожидал, что он будет печатать все цифры от 0до 9?
Ответы:
Потому что это две разные вещи. Это {1,2,3}пример расширения скобки . {1,2,3}Конструкция расширяется оболочкой , до того echoдаже не видит. Вы можете увидеть, что произойдет, если вы используете set -x:
$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3
Как видите, команда echo {1,2,3}расширена до:
echo 1 2 3
Тем не менее, [[:digit:]]это класс символов POSIX . Когда вы передаете его echo, оболочка также сначала обрабатывает его, но на этот раз он обрабатывается как глобус оболочки . это работает так же, как если бы вы запустили, echo *который напечатает все файлы в текущем каталоге. Но [[:digit:]]это оболочка Глобо , которая будет соответствовать любой цифре. Теперь в bash, если глобус оболочки ничего не соответствует, он будет расширен до самого себя:
$ echo /this*matches*no*files
+ echo '/this*matches*no*files'
/this*matches*no*files
Если шарик совпадает с чем-то, это будет напечатано:
$ echo /e*c
+ echo /etc
/etc
В обоих случаях echoпросто печатает все, что говорит оболочка, чтобы распечатать, но во втором случае, так как глобус совпадает с чем-то ( /etc), ему говорят, что это нужно напечатать.
Итак, поскольку у вас нет файлов или каталогов, чье имя состоит ровно из одной цифры (что [[:digit:]]соответствует), глобус расширяется до самого себя, и вы получаете:
$ echo [[:digit:]]
[[:digit:]]
Теперь попробуйте создать файл с именем 5и запустить ту же команду:
$ echo [[:digit:]]
5
И если есть несколько подходящих файлов:
$ touch 1 5
$ echo [[:digit:]]
1 5
Это (вроде) задокументировано в man bashобъяснении nullglobопций, которые отключают это поведение:
nullglob
If set, bash allows patterns which match no files (see
Pathname Expansion above) to expand to a null string,
rather than themselves.
Если вы установите эту опцию:
$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]] ## prints nothing
$
shopt -s failglobчтобы получить более полезное поведение, подобное поведению современных оболочек типа zshor fish.
failglob. nullglobможет вызвать непредвиденные проблемы, например, при вставке URL, который имеет ?.
nullglobчтобы продемонстрировать, что паттерн интерпретируется оболочкой как глобус.
{1,2,3}это расширение скобки , оно распространяется на слова, перечисленные без учета их значения.
[...]является группой символов, используемой в расширении имени файла (или подстановочный знак, или глобус) аналогично звездочке *и вопросительному знаку ?. Он соответствует любому отдельному символу в списке или символам, которые являются членами именованных групп, например, [:digit:]если они есть в списке. Поведение большинства оболочек по умолчанию - оставить подстановочный знак как есть, если нет файлов, соответствующих ему.
(Обратите внимание, что вы действительно не можете превратить подстановочный знак / шаблон в набор строк, которому он будет соответствовать. Звездочка может соответствовать любой строке любой длины, поэтому расширение любого шаблона, содержащего ее, приведет к бесконечному списку строк.)
Так:
$ bash -c 'echo [[:digit:]]' # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]' # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]' # now there are two matches
1 3 # note that d, i, g and t do NOT match
Но до сих пор:
$ bash -c 'echo {1,2,3}'
1 2 3
Оба они расширяются оболочкой , не имеет значения, является ли команда, которую вы запускаете ls, или, echoили rm. Также обратите внимание, что если один из них указан в кавычках, они не будут расширены:
$ bash -c 'echo "[[:digit:]]"' # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}
[[:digit:]] перед передачей ее echo, поэтому echoникогда не видит [[:digit:]], она видит только 1 3. Вы можете увидеть это в действии, запустив, set -xкоторый напечатает фактические команды, которые выполняются (запустите, set +xчтобы выключить его снова).
echoне ищет файлы, это делает оболочка перед запуском echo.
{1,2,3}(и, например, {1..3}это фигурные расширения . Они интерпретируются оболочкой перед выполнением команды.
[[:digit:]]это токен, соответствующий шаблону , но вы не используете его в расположении с файлами, соответствующими этому шаблону. Если вы используете сопоставление с шаблоном, у которого нет совпадений, оно расширяется до самого себя:
$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3