2012-04-16 23 views
5

Estoy tratando de hacer un pequeño script bash que limpiará los nombres de archivos y carpetas de episodios descargados de algunos programas de televisión que me gustan. A menudo se ven como "[www.Speed.Cd] - Some.Show.S07E14.720p.HDTV.X264-ALGUIEN", y básicamente solo quiero quitar ese bit de publicidad speedcd.coincidencia de expresiones regulares de BASH, incluidos los corchetes en una lista de caracteres entre corchetes para hacer coincidir?

Es bastante fácil eliminar www.Speed.Cd, espacios y guiones usando correspondencias de expresiones regulares en BASH, pero por mi vida, no puedo encontrar la manera de incluir los corchetes en una lista de caracteres con los que comparar . [- [] no funciona, tampoco lo hace [- \ [], [- \\ [], [- \\\ [] o cualquier cantidad de caracteres de escape que preceden al corchete que deseo eliminar.

Esto es lo que tengo hasta ahora:

[[ "$newfile" =~ ^(.*)([- \[]*(www\.torrenting\.com|spastikustv|www\.speed\.cd|moviesp2p\.com)[- \]]*)(.*)$ ]] && 
    newfile="${BASH_REMATCH[1]}${BASH_REMATCH[4]}" 

pero se degrada en los soportes.

¿Alguna idea?

TIA, Daniel :)

EDIT: Probablemente debería notar que estoy usando "shopt -s nocasematch" para garantizar la coincidencia insensible caso, sólo en caso de que se esté preguntando :)

EDIT 2: Gracias a todos los que contribuyeron. No estoy 100% seguro de cuál respuesta fue la "correcta", ya que tuve varios problemas con mi afirmación. En realidad, la respuesta más precisa fue solo un comentario a mi pregunta publicada por jw013, pero no lo entendí en ese momento porque aún no había entendido que se debían escapar los espacios. He optado por aefxx, ya que básicamente dice lo mismo, pero con explicaciones :) Me hubiera gustado poner una respuesta correcta en la respuesta de ormaj, también, ya que vio problemas más graves con mi expresión.

De todos modos, el enfoque que estaba usando arriba, tratando de unir y extraer las partes para mantener y dejar atrás las no deseadas realmente no es muy elegante, y no detectará todos los casos, ni siquiera algo realmente simple como "Algunos .Show.S07E14.720p.HDTV.X264-ALGUIEN - [www.Speed.Cd] ". en cambio me he reescrito para que coincida y extraer sólo las partes no deseadas y luego hacer sustitución de cadenas de los de la cadena original, al igual que (bucle es en caso de que haya varios brandings):

# Remove common torrent site brandings, including surrounding spaces, brackets, etc.: 
while [[ "$newfile" =~ ([[\ {\(-]*(www\.)?(torrentday\.com|torrenting\.com|spastikustv|speed\.cd|moviesp2p\.com|publichd\.org|publichd|scenetime\.com|kingdom-release)[]\ }\)-]*) ]]; do 
    newfile=${newfile//"${BASH_REMATCH[1]}"/} 
done 
+0

en lugar de '[- \ []' 'tratar [- \ []' 'y en lugar de [- \]]' 'tratar [] - \]'. – jw013

+0

Gracias, pero no rosquilla en cualquiera :( Alguna idea sobre esos? AFAICT, el primero que se escapa al espacio, y en cuanto a la segunda, la guía de BASH establece que cuando se utiliza un guión como un literal (en lugar de especificar una gama), tiene que venir como el primer carácter – DanielSmedegaardBuus

Respuesta

7

Ok, esta es la primera vez que he oído del operador =~ pero sin embargo esto es lo que encontré por prueba y error:

if [[ $newfile =~ ^(.*)([-[:space:][]*(what|ever)[][:space:]-]*)(.*)$ ]] 
          ^^^^^^^^^^    ^^^^^^^^^^ 

Parece extraño, pero en realidad funciona (simplemente lo probé).

EDITAR
Presupuesto de la Linux páginas del manual de expresiones regulares (7):

To include a literal ] in the list, make it the first character (following a possible ^). To include a literal -, make it the first or last character, or the second endpoint of a range. To use a literal aq-aq as the first endpoint of a range, enclose it in "[." and ".]" to make it a collating element (see below). With the exception of these and some combinations using aq[aq (see next paragraphs), all other special characters, including aq\aq, lose their special significance within a bracket expression.

+0

De hecho, me olvidé de ese truco. Se menciona en uno de los primeros dos párrafos de regex (7) de las páginas de manual de Linux. – ormaaj

+0

¡Este coincide con el soporte de cierre, incluidos todos los espacios y guiones que lo rodean! ¡Gracias! Sin embargo, todavía tiene el primer subcompañero comiendo el paréntesis inicial, pero eso no es un problema :) – DanielSmedegaardBuus

+0

Oh, no me molesté con los subpatrones ya que pensé que el problema real es el (aparentemente) imposible escape de esos paréntesis. – aefxx

0

Usted puede intentar algo así como esto (aunque no estaban 100% claro en qué casos se trate de filtrar:

newfile="[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE" 

if [[ $newfile =~ ^(.*)([^a-zA-Z0-9.]*\[.*\][^a-zA-Z0-9.]*)(.*)$ ]]; then 
    newfile="${BASH_REMATCH[1]}${BASH_REMATCH[3]}" 
fi 

echo $newfile 
# Some.Show.S07E14.720p.HDTV.X264-SOMEONE 

Su justo despojar cualquier no alnum (y punto) caracteres fuera del [], y cualquier cosa dentro de []

+0

@DanielSmedegaardBuus:? la única gama de personajes que estoy especificando son aquellos que no ** ** ser válido es mucho más abierta que la forma en que está codificando sitio URLs – jdi

+0

. Lo siento, @jdi, me perdí tu punto. Sin embargo, específicamente estoy tratando de eliminar URL específicas en esta notación en particular, e incluso cuando tu sugerencia funciona para este caso en particular, simplemente elimina cualquier cosa entre paréntesis, y realmente podría ser más delgada a "[[$ nuevofichero = ~^(\\ [* \\].) $] (*). (*.)]" AFAICT – DanielSmedegaardBuus

+0

@DanielSmedegaardBuus:. AFAICT que no coinciden con la misma Considere "Algunas cosas. aquí - [www. Speed.Cd] - Some.Show.S07E14.720p.HDTV.X264-ALGUIEN " – jdi

4

Cada vez que estás haciendo un re gex es más compatible entre versiones de Bash para poner expresiones regulares en una variable incluso si logras esquivar todas las trampas de ponerlas directamente en una expresión de prueba. http://mywiki.wooledge.org/BashPitfalls#if_.5B.5B_.24foo_.3D.2BAH4_.27some_RE.27_.5D.5D

Su regex actual parece que está intentando hacer coincidir cualquier cosa que preceda al corchete de apertura.Supongo que en realidad está tratando de ahorrar, por ejemplo, 3 y 4 de algo como esto:

$ shopt -s nocasematch 
$ newfile='[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE' 
$ re='^.*[-[:space:][]*(www\.torrenting\.com|spastikustv|www\.speed\.cd|moviesp2p\.com)[][:space:]-]*(.*)$' 
$ [[ $newfile =~ $re ]] 
$ declare -p BASH_REMATCH 
declare -ar BASH_REMATCH='([0]="[ www.Speed.Cd ] - Some.Show.S07E14.720p.HDTV.X264-SOMEONE" [1]="www.Speed.Cd" [2]="Some.Show.S07E14.720p.HDTV.X264-SOMEONE")' 
+0

En realidad, como he habilitado la coincidencia de mayúsculas y minúsculas, el principal problema parece ser mi asterisco "cero o más instancias" en el subpatrón dos, de modo que el primer subpattern comerá más de lo debido (porque no tiene un paréntesis inicial) dejado sin comer todavía hace que los dos subpatrones sean válidos). Tu sugerencia evita eso. – DanielSmedegaardBuus

+0

Estaba pensando en hacer lo mismo, es decir, hacer coincidir cualquier cosa que no fuera un paréntesis inicial para el subpatrón 1, pero quería ser "más genérico", y no exigir que el soporte estuviera allí, ya que a veces simplemente lo pondrían "- algunos. tracker.org "al final o lo que sea".Pero en serio, es un caso de esquina con el que tendré que vivir :) OTOH, todavía no puedo entender por qué el patrón que se supone que se come el corchete derecho y los espacios y/o guiones circundantes no lo está comiendo. todo, ni en mi código ni en el tuyo (es decir [4] = "- Some.Show.S07E14.720p.HDTV.X264-ALGUIEN, que me gustaría no tener el liderazgo" - "). – DanielSmedegaardBuus

+0

Estoy Voy a trabajar en eso ahora, pero si lo encuentras, házmelo saber;) ¡Gracias! – DanielSmedegaardBuus

1

La cuestión básica es muy simple, si no es obvio.
A BASH Regex es totalmente sin protección (de la cáscara), y no puede ser protegido por " comillas dobles ". Esto significa que cada espacio literal (y la ficha, etc.) deben ser protegido por un baskslash \ ... fin de la historia. El resto es solo un caso de obtenerle expresiones regulares para satisfacer sus necesidades.

Una cosa más; utilizar [\ [] y []\ ] para que coincida con [ y ] respectivamente, dentro de la construcción gama de corchetes (en este caso junto con un espacio).

ejemplo:

newfile="[ ]" 
[[ "$newfile" =~ ^[\ []\ []\ ]$ ]] && 
    echo YES || 
    echo NO 
Cuestiones relacionadas