Estou substituindo, de um título de feed, todos os caracteres, exceto letras e dígitos, por um traço para usar o resultado como um nome de arquivo seguro para qualquer sistema de arquivos:
$ 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
No entanto, eu gostaria de condensar todos os traços repetidos com um único Episodie-06-No-hope-of-riding-home-NEW-Advanced-grammar
Descobri que posso consegui-lo usando uma substituição de duas passagens:
$ 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
Eu pensei que poderia fazê-lo em uma única passagem como:
$ echo ${t//[^A-Za-z0-9]+/-}
mas não funciona.
Qualquer pista?
Nota: não quero usar sed
nem outras ferramentas
shopt
quais conchas o suportam.shopt
é específico para o bash. A sintaxe de padrão que ele habilita está sempre disponível em todas as variantes do ksh. No zsh, essa sintaxe deve ser ativada comsetopt ksh_glob
. O POSIX não possui esse recurso, seus curingas são menos poderosos que os regexps. Os shells que não sejam bash / ksh / zsh, que na prática geralmente significam cinzas hoje em dia, tendem a seguir os curingas POSIX.echo "$t" | sed -r 's/[^[:alnum:]]+/-/g; s/^-|-$//'
. Aceito sua resposta, pois faz exatamente o que foi solicitado em questão.${var/PATTERN/REPLACEMENT}
construção também é específica para ksh / bash / zsh.sed
que conheça melhor sua sintaxe e comportamento, posso adicionar facilmente uma instrução para remover traços iniciais / finais, não preciso me preocupar com\n
char. Ésed
muito menos disponível do quetr
?tr
é uma boa ferramenta para este trabalhofonte
tr
... No entanto, eu estava tentando fazê-lo em Bash, caso contrário, eu iria comsed
:echo "$t" | sed -r 's/[^A-Za-z0-9]+/-/g'
Note: I don't want to go with sed or other tools
Se você quiser ficar com o bash puro, terá que se contentar com a solução de duas passagens. As substituições de string Bash usam globs , como na expansão do nome do caminho, e não expressões regulares. Os únicos caracteres especiais em globs são
*
,?
e[]
, cujo áspero equivalentes em expressões regulares são.*
,.
e[]
. Dê uma olhada no wiki do Wooledge e nas seções da página de manual e para mais informações.bash(1)
Parameter Expansion
Pathname Expansion
Apenas como comentário, é provável que uma expansão de duas passagens no bash puro seja mais rápida do que tentar fazer a mesma coisa invocando um programa externo, para que eu não me preocupasse muito com isso.
fonte
shopt -s extglob; t="${t//+([^A-Za-z0-9])/-}"