Я заменяю из заголовка канала все символы, кроме букв и цифр, тире, чтобы использовать результат в качестве безопасного имени файла для любой файловой системы:
$ t="Episodie 06: No hope of riding home (NEW) - Advanced grammar"
$ echo ${t//[^A-Za-z0-9]/-}
Episodie-06--No-hope-of-riding-home--NEW----Advanced-grammar
Однако я бы хотел сжать все повторяющиеся тире одним Episodie-06-No-hope-of-riding-home-NEW-Advanced-grammar
Я обнаружил, что могу добиться этого с помощью двухпроходной замены:
$ t="Episodie 06: No hope of riding home (NEW) - Advanced grammar"
$ tmp=${t//[^A-Za-z0-9]/-}
$ echo ${tmp//--/-}
Episodie-06-No-hope-of-riding-home-NEW--Advanced-grammar
Я думал, что смогу сделать это за один проход, например:
$ echo ${t//[^A-Za-z0-9]+/-}
но это не работает
Любая подсказка?
Примечание: я не хочу использовать sed
другие инструменты
shopt
какие оболочки поддерживают это.shopt
специфичен для bash. Синтаксис шаблона, который он включает, всегда доступен во всех вариантах ksh. В zsh этот синтаксис должен быть включен сsetopt ksh_glob
. POSIX не имеет такой функции, его шаблоны являются менее мощными, чем регулярные выражения. Оболочки, отличные от bash / ksh / zsh, которые на практике в настоящее время в основном означают пепел, обычно придерживаются подстановочных знаков POSIX.echo "$t" | sed -r 's/[^[:alnum:]]+/-/g; s/^-|-$//'
. Я принимаю ваш ответ, поскольку он точно делает то, что задал вопрос.${var/PATTERN/REPLACEMENT}
конструкция также специфична для ksh / bash / zsh.sed
поскольку я лучше знаю его синтаксис и поведение, я могу легко добавить оператор для удаления начальных / конечных тире, мне не нужно заботиться о\n
символе. Является лиsed
способ менее доступным, чемtr
?tr
хороший инструмент для этой работыисточник
tr
... Однако я пытался сделать это в Bash, иначе я бы пошел сsed
:echo "$t" | sed -r 's/[^A-Za-z0-9]+/-/g'
Note: I don't want to go with sed or other tools
Если вы хотите остаться с чистым bash, вам придется согласиться на двухходовое решение. Подстановки строк Bash используют глобусы , как в раскрытии пути, а не регулярные выражения. Только специальные символы в комках являются
*
,?
и[]
, чьи грубыми эквивалентами в регулярных выражениях.*
,.
и[]
. Посмотрите вики Wooledge и разделы справочной страницы на и для получения дополнительной информации.bash(1)
Parameter Expansion
Pathname Expansion
Так же, как комментарий, двухпроходное расширение в чистом bash все еще, вероятно, будет быстрее, чем пытаться сделать то же самое, вызывая внешнюю программу, так что я бы не слишком беспокоился об этом.
источник
shopt -s extglob; t="${t//+([^A-Za-z0-9])/-}"