Estoy reemplazando, desde un título de fuente, todos los caracteres, excepto letras y dígitos, con un guión para usar el resultado como un nombre de archivo seguro para cualquier sistema de archivos:
$ 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
Sin embargo, me gustaría condensar todos los guiones repetidos con uno solo como Episodie-06-No-hope-of-riding-home-NEW-Advanced-grammar
Descubrí que puedo lograrlo usando una sustitución de dos pases:
$ 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
Pensé que podría hacerlo en una sola pasada como:
$ echo ${t//[^A-Za-z0-9]+/-}
Pero no funciona.
¿Cualquier pista?
Nota: no quiero ir con sed
u otras herramientas
shopt
y qué shells lo respaldan.shopt
es específico de bash. La sintaxis del patrón que habilita siempre está disponible en todas las variantes de ksh. En zsh, esta sintaxis debe habilitarse consetopt ksh_glob
. POSIX no tiene esa característica, sus comodines son menos potentes que las expresiones regulares. Los shells que no sean bash / ksh / zsh, que en la práctica en su mayoría significa ceniza hoy en día, tienden a adherirse a los comodines POSIX.echo "$t" | sed -r 's/[^[:alnum:]]+/-/g; s/^-|-$//'
. Acepto su respuesta, ya que hace exactamente lo que se preguntó.${var/PATTERN/REPLACEMENT}
construcción también es específica de ksh / bash / zsh.sed
ya que conozco mejor su sintaxis y comportamiento, puedo agregar fácilmente una declaración para eliminar guiones iniciales / finales, no necesito preocuparme por\n
char. ¿Essed
mucho menos disponible quetr
?tr
es una buena herramienta para este trabajofuente
tr
... Sin embargo, estaba tratando de hacerlo en Bash, de lo contrario iría consed
:echo "$t" | sed -r 's/[^A-Za-z0-9]+/-/g'
Note: I don't want to go with sed or other tools
Si quieres quedarte con puro bash, tendrás que conformarte con la solución de dos pasos. Las sustituciones de cadena bash usan globos , como en la expansión del nombre de ruta, y no expresiones regulares. Los únicos caracteres especiales en globos son
*
,?
y[]
, cuya áspera equivalentes en las expresiones regulares son.*
,.
y[]
. Eche un vistazo a la wiki de Wooledge y las secciones de la página de manual en y para obtener más información.bash(1)
Parameter Expansion
Pathname Expansion
Como comentario, es probable que una expansión de dos pasos en bash puro sea más rápida que intentar hacer lo mismo invocando un programa externo, por lo que no me preocuparía demasiado.
fuente
shopt -s extglob; t="${t//+([^A-Za-z0-9])/-}"