Jeśli używasz Bash, nie musisz nawet używać 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
Lepiej umieścić regex w zmiennej. Niektóre wzory nie będą działać, jeśli zostaną dosłownie uwzględnione.
Wykorzystuje =~
to, który jest operatorem dopasowania wyrażenia regularnego Basha. Wyniki dopasowania są zapisywane w tablicy o nazwie $BASH_REMATCH
. Pierwsza grupa przechwytywania jest przechowywana w indeksie 1, druga (jeśli istnieje) w indeksie 2 itd. Indeks zero jest pełnym dopasowaniem.
Należy pamiętać, że bez kotwic, to wyrażenie regularne (i ten używający grep
) będzie pasować do dowolnego z następujących przykładów i nie tylko, które mogą nie być tym, czego szukasz:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Aby wyeliminować drugi i czwarty przykład, wykonaj wyrażenie regularne w ten sposób:
^[0-9]+_([a-z]+)_[0-9a-z]*
co oznacza, że ciąg musi zaczynać się od jednej lub więcej cyfr. Karat reprezentuje początek łańcucha. Jeśli dodasz znak dolara na końcu wyrażenia regularnego, w ten sposób:
^[0-9]+_([a-z]+)_[0-9a-z]*$
wtedy trzeci przykład również zostanie wyeliminowany, ponieważ kropka nie znajduje się wśród znaków w wyrażeniu regularnym, a znak dolara reprezentuje koniec łańcucha. Zauważ, że czwarty przykład również nie pasuje do tego dopasowania.
Jeśli masz GNU grep
(około 2,5 lub później, myślę, że kiedy \K
operator został dodany):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
\K
Uruchamiający (o zmiennej długości wygląd opóźnieniem) powoduje, że powyższy wzór do meczu, ale nie obejmuje dopasowanie w wyniku. Odpowiednikiem o stałej długości jest (?<=)
- wzorzec zostanie dołączony przed nawiasem zamykającym. Należy użyć \K
, jeśli kwantyfikatory mogą dopasować ciągi o różnej długości (na przykład +
, *
, {2,4}
).
Te (?=)
mecze operatora stałej lub zmiennej długości wzory i nazywa się „look-ahead”. Nie zawiera również dopasowanego ciągu w wyniku.
Aby uczynić dopasowanie bez rozróżniania wielkości liter, (?i)
używany jest operator. Wpływa na wzorce, które za nim podążają, więc jego pozycja jest znacząca.
Wyrażenie regularne może wymagać dostosowania w zależności od tego, czy w nazwie pliku znajdują się inne znaki. Zauważysz, że w tym przypadku pokazuję przykład konkatenacji łańcucha w tym samym czasie, gdy przechwytywany jest podciąg.