Si está usando Bash, ni siquiera tiene que usar grep
:
files="*.jpg"
regex="[0-9]+_([a-z]+)_[0-9a-z]*"
for f in $files # unquoted in order to allow the glob to expand
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 utiliza =~
cuál es el operador de coincidencia de expresiones regulares de Bash. Los resultados del partido se guardan en una matriz llamada $BASH_REMATCH
. El primer grupo de captura se almacena en el índice 1, el segundo (si lo hay) en el índice 2, etc. El índice cero es la coincidencia completa.
Debe tener en cuenta que sin las anclas, esta expresión regular (y la que usa grep
) coincidirá con cualquiera de los siguientes ejemplos y más, que pueden 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, haga su expresión regular de esta manera:
^[0-9]+_([a-z]+)_[0-9a-z]*
que dice que la cadena debe comenzar con uno o más dígitos. El quilate representa el comienzo de la cadena. Si agrega un signo de dólar al final de la expresión regular, así:
^[0-9]+_([a-z]+)_[0-9a-z]*$
entonces el tercer ejemplo también será eliminado ya que el punto no está entre los caracteres en la expresión regular y el signo de dólar representa el final de la cadena. Tenga en cuenta que el cuarto ejemplo también falla en esta coincidencia.
Si tiene GNU grep
(alrededor de 2.5 o posterior, creo, cuando \K
se agregó el operador):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
El \K
operador (retrospectiva de longitud variable) hace que el patrón anterior coincida, pero no incluye la coincidencia 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 (p +
. Ej . *
, {2,4}
).
El (?=)
operador coincide con patrones de longitud fija o variable y se llama "mirar hacia adelante". Tampoco incluye la cadena coincidente en el resultado.
Para que la coincidencia no distinga entre mayúsculas y minúsculas, (?i)
se utiliza el operador. Afecta los patrones que lo siguen, por lo que su posición es significativa.
Es posible que sea necesario 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.