Регулярные выражения, конец строки и Bashscript просто не будут работать вместе

В настоящее время я пишу сценарий bash для переименования файлов. Каждый файл выглядит так: * _ #. Ext где * может быть что угодно и # 9 цифр. В этом примере, плохо придерживаться 3 цифры вместо.

Вот основной пример того, что он должен делать:

Вход: example1_123.jpg Выход: example1.jpg

Достаточно просто? Правильно:

#!/bin/bash
filename="example1_123.jpg"
echo ${filename/_[0-9][0-9][0-9]/}

Выход: example1.jpg

Это работает... пока вход не похож на это имя файла: example2_123.jpg_987.jpg

Файл будет переименован в example2.jpg_987.jpg вместо example2_123.jpg.jpg

я попытался использовать $ для конца строки, но это нарушает его, поскольку $ используется для переменных:

#!/bin/bash
filename="example2_123.jpg_987.jpg"
echo ${filename/_[0-9][0-9][0-9].jpg$/}.${filename/*./}

Результат: example2_123.jpg_987.jpg.jpg\$ также не работает. Я не знаю...

Может ли кто-нибудь помочь мне заставить его работать так, как мне это нужно?

PS [0-9] {3} вместо [0-9] [0-9] [0-9] также нарушает его. Если кто-то знает, как его укоротить, скажите так :)

4 ответа

Использование:

target=$(echo $f | sed 's,_[0-9]\+\(\.[a-z]\+\)$,\1')

Это сделает то, что вы хотите.

fg@erwin ~ $ f=example2_123.jpg_987.png
fg@erwin ~ $ target=$(echo $f | sed 's,_[0-9]\+\(\.[a-z]\+\)$,\1,')
fg@erwin ~ $ echo $target
example2_123.jpg.png
fg@erwin ~ $ f=example1_123.png
fg@erwin ~ $ target=$(echo $f | sed 's,_[0-9]\+\(\.[a-z]\+\)$,\1,')
fg@erwin ~ $ echo $target
example1.png

Surround $(...) с двойными кавычками, если у вас есть имена пространства в $f.

Это sed, поэтому классический диалект regex, поэтому группировка, альтернативы и квантификаторы (ну, кроме *) всем нужно, чтобы им предшествовала обратная косая черта... "Каноническое" регулярное выражение на самом деле:

_[0-9]+(\.[a-z]+)$


$ не используется bash, bash использует префикс%:

echo ${filename/%_[0-9][0-9][0-9].jpg/}.${filename/*./}


Попробуйте ${filename%_[0-9]*.*}.${filename##*.}" Как в этом примере:

for filename in example1_123.jpg example2_123.jpg_987.jpg example2_4.jpg_1.jpg ; do
 echo "$filename -> ${filename%_[0-9]*.*}.${filename##*.}"
done

Это приведет к выводу

example1_123.jpg -> example1.jpg
example2_123.jpg_987.jpg -> example2_123.jpg.jpg
example2_4.jpg_1.jpg -> example2_4.jpg.jpg

Таким образом, всегда удаляем окончательный _, за которым следуют любые цифры.


Я думаю, это то, что вы хотите:

filename="example2_123.jpg_987.jpg"
echo ${filename//_[0-9][0-9][0-9]/}

Таким образом, все _NNN будут заменены. Вышеуказанный результат: example2.jpg.jpg

licensed under cc by-sa 3.0 with attribution.