Якщо ви використовуєте 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_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)
оператор. Це впливає на закономірності, які слідують за ним, тому його позиція є важливою.
Регекс може знадобитися коригувати залежно від того, чи є в імені файла інші символи. Ви зауважите, що в цьому випадку я показую приклад об'єднання рядка одночасно із захопленням підрядків.