A string Bash substitui vários caracteres por um

6

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, gostaria de condensar todos os traços repetidos com um único como 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 achei que poderia fazer isso em uma única passagem como:

$ echo ${t//[^A-Za-z0-9]+/-}

mas não funciona.

Alguma pista?

Nota: não quero ir com sed ou outras ferramentas

    
por neurino 31.10.2011 / 00:04

3 respostas

6

Você precisa de algo mais poderoso que os curingas tradicionais de shell. No bash, defina a opção extglob , que dá acesso a expressões regulares em padrões glob através de uma sintaxe incomum herdada do ksh.

shopt -s extglob
sanitized=${raw//+([^A-Za-z0-9])/-}
    
por 31.10.2011 / 22:14
5

tr é uma boa ferramenta para este trabalho

new=$( printf "%s" "$t" | tr -cs 'a-zA-Z0-9' '-' )
new=${new#-}; new=${new%-}
    
por 31.10.2011 / 14:11
3

Se você quiser ficar com pura bash, você terá que se contentar com a solução de duas passagens. 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 [] , cujos equivalentes aproximados em expressões regulares são .* , . e [] . Dê uma olhada no Wooledge wiki e as seções da página bash(1) man em Parameter Expansion e Pathname Expansion para mais informações.

Assim como um comentário, uma expansão de duas passagens no bash puro ainda será provavelmente mais rápida do que tentar fazer a mesma coisa invocando um programa externo, então eu não me preocuparia muito com isso.

    
por 31.10.2011 / 00:25