Я хотел бы сказать, будет ли строка $string
соответствовать шаблону глобуса $pattern
. $string
может или не может быть имя существующего файла. Как я могу это сделать?
Предположим следующие форматы для моих входных строк:
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
Я хотел бы найти Баш идиому , который определяет , если $string
будет сопровождаться $pattern1
, $pattern2
или любым другим произвольным шаблоном Глоб. Вот что я пробовал до сих пор:
[[ "$string" = $pattern ]]
Это почти работает, за исключением того, что
$pattern
интерпретируется как строковый шаблон, а не как шаблон глобуса.[ "$string" = $pattern ]
Проблема этого подхода заключается в том, что
$pattern
он расширяется, а затем выполняется сравнение строк$string
и расширение$pattern
.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
Это работает, но только если
$string
содержит файл, который существует.[[ $string =~ $pattern ]]
Это не работает, потому что
=~
оператор$pattern
интерпретируется как расширенное регулярное выражение, а не как шаблон глобуса или шаблона.
{bar,baz}
это не шаблон. Это расширение параметров. Тонкое, но критическое различие в этом{bar,baz}
очень рано раскрывается в нескольких аргументах,bar
иbaz
.ls /foo/*
теперь вы можете соответствовать вfoo/{bar,baz}
на самом деле это расширение скобок (не расширение параметров), аfoo/*
расширение путей.$string
это расширение параметра. Все это делается в разное время и разными механизмами.case
глобом , оператор выполняет расширение имени («глобализация») в соответствии с руководством по Bash.Ответы:
Нет общего решения этой проблемы. Причина в том, что в bash расширение скобок (то есть,
{pattern1,pattern2,...}
и расширение имени файла (также называемые шаблонами глобуса) рассматриваются как отдельные вещи и раскрываются в разных условиях и в разное время. Вот полный список расширений, которые выполняет bash:Поскольку мы заботимся только об их подмножестве (например, расширение скобок, тильды и имен путей), можно использовать определенные шаблоны и механизмы для ограничения расширения управляемым образом. Например:
Запуск этого скрипта генерирует следующий вывод:
Это работает, потому что
set -f
отключает расширение имени пути, поэтому в выражении присутствуют только расширение скобки и расширение тильдыfor pattern in /foo/{*,foo*,bar*,**,**/*}
. Затем мы можем использовать тестовую операцию[[ $string == $pattern ]]
для проверки на расширение имени пути после того, как расширение скобки уже выполнено.источник
Я не считаю , что
{bar,baz}
это шаблон оболочки Глоб (хотя , конечно ,/foo/ba[rz]
есть) , но если вы хотите знать , если$string
матчи$pattern
вы можете сделать:Вы можете сделать столько, сколько захотите:
источник
{bar,baz}
это не шаблон. Я уже пришел к решению моего вопроса, который учитывает это.Как отметил Патрик, вам нужен шаблон «другого типа»:
Цитаты там не нужны.
источник
sed
операция.Я бы использовал grep таким образом:
Который дает вывод:
источник
в зш:
источник