Si está usando Bash, que ni siquiera tiene que usar grep
:
files="*.jpg"
regex="[0-9]+_([a-z]+)_[0-9a-z]*"
for f in $files
do
if [[ $f =~ $regex ]]
then
name="${BASH_REMATCH[1]}"
echo "${name}.jpg" # concatenate strings
name="${name}.jpg" # same thing stored in a variable
else
echo "$f doesn't match" >&2 # this could get noisy if there are a lot of non-matching files
fi
done
es mejor poner la expresión regular en una variable. Algunos patrones no funcionarán si se incluyen literalmente.
Esto usa =~
que es el operador de coincidencia de expresiones regulares de Bash. Los resultados de la coincidencia se guardan en una matriz llamada $BASH_REMATCH
. El primer grupo de captura se almacena en el índice 1, el segundo (si hay alguno) en el índice 2, etc. El índice cero es la coincidencia completa.
Debe tener en cuenta que sin anclas, esta expresión regular (y el uso de grep
) coincidirá con cualquiera de los siguientes ejemplos y más, lo que puede no ser lo que está buscando:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Para eliminar los ejemplos segundo y cuarto, que su expresión regular como esto:
^[0-9]+_([a-z]+)_[0-9a-z]*
el cual dice que la cadena debe comenzar con uno o más dígitos. El quilate representa el comienzo de la cadena. Si se agrega un signo de dólar al final de la expresión regular, como esto:
^[0-9]+_([a-z]+)_[0-9a-z]*$
entonces el tercer ejemplo también serán eliminados desde el punto no se encuentra entre los personajes de la expresión regular y de dólar representa el final de la cuerda. Tenga en cuenta que el cuarto ejemplo también falla esta coincidencia.
Si tiene GNU grep
(alrededor de 2.5 o posterior, creo que, cuando se agregó el operador \K
):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
El \K
operador (de longitud variable mirada-detrás) hace que el patrón precedente para que coincida , pero no incluye el partido en el resultado. El equivalente de longitud fija es (?<=)
- el patrón se incluiría antes del paréntesis de cierre. Debe usar \K
si los cuantificadores pueden coincidir con cadenas de diferentes longitudes (por ejemplo, +
, *
, {2,4}
).
El operador (?=)
coincide con los patrones de longitud fija o variable y se denomina "anticipación". Tampoco incluye la cadena coincidente en el resultado.
Con el fin de que la coincidencia no distinga entre mayúsculas y minúsculas, se utiliza el operador (?i)
. Afecta los patrones que lo siguen, por lo que su posición es significativa.
Es posible que haya que ajustar la expresión regular dependiendo de si hay otros caracteres en el nombre del archivo. Notarás que en este caso, muestro un ejemplo de concatenación de una cadena al mismo tiempo que se captura la subcadena.
¿Es grep * really * purer unix than sed? –
Ah, no quise sugerir eso. Solo esperaba encontrar una solución usando una herramienta que estoy tratando de aprender aquí. Si no es posible resolver usando 'grep', entonces' sed' sería genial, si es posible resolverlo con 'sed'. – Isaac
Debería haber puesto un :) en ese por cierto ... –