Как перебрать несколько файлов, используя строки из двух входных файлов в качестве начала и конца шаблона?

Используйте printf со строкой формата, которая определяет ширину поля и заполнение нулями для целых чисел, например

printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"

Обратите внимание на использование $ ((10 # $ {BASH_REMATCH [n]})) для принудительного вычисления десятичной дроби в таких случаях, как 09

Тестирование (я немного изменил ваше регулярное выражение BTW ):

reg='^([^0-9]*)([0-9][0-9]*)[^0-9]*([0-9][0-9]*)(\....)$'
for filename in *.mp4; do
  if [[ $filename =~ $reg ]]; then
    printf -v newname 'S%02dE%02d%s' "$((10#${BASH_REMATCH[2]}))" "$((10#${BASH_REMATCH[3]}))" "${BASH_REMATCH[4]}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4


Возможно, более надежным было бы использовать регулярное выражение только для сопоставления первых двух последовательностей цифр и использовать подстановку параметров оболочки для обработки расширения:

reg='([0-9][0-9]*)[^0-9]*([0-9][0-9]*)'
for filename in *.mp4 *.mkv; do
  name="${filename%.*}"
  ext="${filename##*.}"
  if [[ $name =~ $reg ]]; then
    printf -v newname 'S%02dE%02d.%s' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))" "${ext}"
    echo mv "$filename" "$newname"
  fi
done
mv Some Series01.Episode02.mp4 S01E02.mp4
mv SomeSeries09Episode10.mp4 S09E10.mp4
mv SomeSeries1Episode03.mp4 S01E03.mp4
mv Some_Series.1_Episode.1.mp4 S01E01.mp4
mv Breaking.Bad.S01E01.576p.BluRay.DD5.1.x264-HiSD.mkv S01E01.mkv

В качестве альтернативы, если в вашей системе есть на основе perl переименовать / prename команду, вы могли бы что-то вроде

prename -vn -- 's/.*(\d+).*(\d+)/sprintf "S%02dE%02d.mp4", $1, $2/e' *.mp4
3
13.03.2017, 17:10
2 ответа

Постройте шаблон из списков слов. Из file1.txt, содержащего, например, one, un, eins и file2. txt, содержащий two, deux, zwei, необходимо получить регулярное выражение (в синтаксисе ERE)

(one|un|eins).*(two|deux|zwei)

Если списки слов не содержат специальных символов в regex, то достаточно заменить новые строки на | (оператор "или"), кроме последней.

words1=$(tr '\n' '|' <file1.txt); words1=${words1%\|}
words2=$(tr '\n' '|' <file2.txt); words2=${words2%\|}
grep -E "($words1).*($words2)"

Если списки слов могут содержать специальные символы, то их нужно заключить в кавычки.

words1=$(<file1.txt tr '\n' '|' | sed 's/[][\\().*?+|]/\\&/g'); words1=${words1%\|}
words2=$(<file2.txt tr '\n' '|' | sed 's/[][\\().*?+|]/\\&/g'); words2=${words2%\|}
grep -E "($words1).*($words2)"

Обратите внимание, что если вам не важен порядок слов и вы можете принять перекрывающиеся совпадения (например, принять twone как содержащий и one и two), то все, что вам нужно, это два вызова grep:

grep -f file1.txt | grep -f file2.txt
0
27.01.2020, 21:25

Сначала вам нужно экранировать специальные символы в этих двух файлах (если есть), а затем присоединить их, например, вставьте , чтобы получить список шаблонов, которые вы затем использовали бы через grep -f ... и если у вас не слишком много файлов, которые вы не используете Цикл не нужен, поскольку grep принимает несколько аргументов:

paste -d'.*' <(sed 's/[.[\*^$]/\\&/g' file1.txt) /dev/null \
<(sed 's/[.[\*^$]/\\&/g' file2.txt) | grep -f - /root/listoffiles/*php >> found.txt
2
27.01.2020, 21:25

Теги

Похожие вопросы