Если вы используете Bash, вам даже не нужно использовать 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
Лучше поместить регулярное выражение в переменную. Некоторые шаблоны не будут работать, если включены буквально.
Используется =~
оператор Bash для регулярных выражений. Результаты матча сохраняются в массиве с именем $BASH_REMATCH
. Первая группа захвата сохраняется в индексе 1, вторая (если есть) в индексе 2 и т. Д. Индекс ноль - это полное совпадение.
Вы должны знать, что без якорей это регулярное выражение (и то, которое использует grep
) будет соответствовать любому из следующих примеров и более, которые могут не соответствовать тому, что вы ищете:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Чтобы исключить второй и четвертый примеры, сделайте свое регулярное выражение следующим образом:
^[0-9]+_([a-z]+)_[0-9a-z]*
который говорит, что строка должна начинаться с одной или нескольких цифр. Карат представляет начало строки. Если вы добавите знак доллара в конце регулярного выражения, вот так:
^[0-9]+_([a-z]+)_[0-9a-z]*$
тогда третий пример также будет исключен, поскольку точка не находится среди символов в регулярном выражении, а знак доллара представляет конец строки. Обратите внимание, что четвертый пример также не соответствует этому совпадению.
Если у вас есть GNU grep
(около 2,5 или более поздней версии, я думаю, когда \K
оператор был добавлен):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
\K
Оператор ( с переменной длиной смотреть-сзади) вызывает предыдущий образец , чтобы соответствовать, но не включает в себя матч в результате. Эквивалент фиксированной длины (?<=)
- шаблон будет включен перед закрывающей скобкой. Вы должны использовать , \K
если кванторы могут соответствовать строки различной длины (например +
, *
, {2,4}
).
В (?=)
операторе соответствует фиксированному или модели переменной длины и называются «упреждающим». Это также не включает совпавшую строку в результат.
Чтобы сделать совпадение без учета регистра, используется (?i)
оператор. Это влияет на паттерны, которые следуют за ним, поэтому его положение является значительным.
Регулярное выражение может потребоваться изменить в зависимости от того, есть ли в имени файла другие символы. Вы заметите, что в этом случае я показываю пример объединения строки в то же время, когда подстрока захвачена.