Se você estiver usando o Bash, nem precisará 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
É melhor colocar o regex em uma variável. Alguns padrões não funcionarão se incluídos literalmente.
Isso usa =~
qual é o operador de correspondência de regex do Bash. Os resultados da correspondência são salvos em uma matriz chamada $BASH_REMATCH
. O primeiro grupo de captura é armazenado no índice 1, o segundo (se houver) no índice 2, etc. O índice zero é a correspondência completa.
Você deve estar ciente de que, sem âncoras, essa regex (e a que está sendo usada grep
) corresponderá a qualquer um dos seguintes exemplos e mais, que pode não ser o que você está procurando:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Para eliminar o segundo e o quarto exemplos, faça sua regex assim:
^[0-9]+_([a-z]+)_[0-9a-z]*
que diz que a sequência deve começar com um ou mais dígitos. O quilate representa o início da string. Se você adicionar um cifrão no final da regex, faça o seguinte:
^[0-9]+_([a-z]+)_[0-9a-z]*$
o terceiro exemplo também será eliminado, pois o ponto não está entre os caracteres na regex e o cifrão representa o final da string. Observe que o quarto exemplo também falha nessa correspondência.
Se você possui o GNU grep
(por volta de 2.5 ou posterior, acho, quando o \K
operador foi adicionado):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
O \K
operador (look-behind de comprimento variável) faz com que o padrão anterior corresponda, mas não inclui a correspondência no resultado. O equivalente de comprimento fixo é (?<=)
- o padrão seria incluído antes do parêntese de fechamento. Você deve usar \K
se os quantificadores podem coincidir com cordas de comprimentos diferentes (por exemplo +
, *
, {2,4}
).
O (?=)
operador corresponde a padrões de comprimento fixo ou variável e é chamado de "antecipação". Também não inclui a sequência correspondente no resultado.
Para fazer a correspondência não diferenciar maiúsculas de minúsculas, o (?i)
operador é usado. Afeta os padrões que o seguem, portanto sua posição é significativa.
A regex pode precisar ser ajustada, dependendo da existência de outros caracteres no nome do arquivo. Você notará que, neste caso, mostro um exemplo de concatenação de uma sequência de caracteres ao mesmo tempo em que a substring é capturada.