Любые способы улучшить это однострочное регулярное выражение?

Не рекомендуется разбирать ls, поэтому в вашем случае cdв каталог и используйте это:

 for CA in $(find. -maxdepth 1 -type f -name ContractAdjustments\*.txt | head --lines=-1); do mv $CA /path/to/archive/; done

Использование цикла forс подстановкой команд, который находит все файлы в каталоге, начиная с указанного вами формата ContractAdjustments*.txt, и перечисляет их в порядке от самых старых до самых новых в соответствии с датой создания. второй октет. Затем он передается в --head --lines=-1, который печатает все, кроме последней строки, которая является самым новым файлом, и передает значение в переменную CA(для ContractAdjustments ). Наконец, doиспользует mvдля перемещения всех файлов, кроме самого нового, в расположение архива.

2
21.04.2020, 22:52
6 ответов

Понял, что вопрос на самом деле касается regex, представленного так же, как я бы не стал ломать себе мозг и

for m in *.mkv; 
    do echo mv $m "$(awk -F'.' '{
        printf "%s %s %s - %s - %s %s.%s", $1, $2, $3, $4, $5, $6, $(NF)}' <<<$m)";
done

Предсказуемый, легко читаемый, а также легко модифицируемый вывод строки. Просто удалитеecho

РЕДАКТИРОВАТЬ

Что касается вашего комментария ниже о sed, вы можете использовать ту же технику, просто обработав имя файла для вывода, используя sedвместоawk

for m in *.mkv; 
    do echo mv $m "$(sed 's/\./ /1;s/\./ /1;s/\./ - /1;s/\./ - /1;s/\./ /1;s/\..*\././' <<<$m)";
done
3
19.03.2021, 02:28

вместо этого вы можете использовать sed.

sed 's/\./ /1;s/\./ /1;s/\./ - /1;s/\./ - /1;s/\./ /1;s/\.1080p\.Uploader\.mkv/\.mkv/1;'

он заменяет первое вхождение точки каждый раз.

0
19.03.2021, 02:28

Вы могли бы сделать это:

$ rename -n 's/.(S\d+E\d+)./ - $1 - /; s/\./ /g; s/\.1080p.+\././' *mkv
TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv -> TV Show Title - SXEY - Episode Title 1080p Uploader mkv

Или это:

$ rename -n 's/1080p.*\.//; s/\.(?!mkv)/ /g; s/S\d+E\d+/- $& -/' *mkv
TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv -> TV Show Title - SXEY - Episode Title.mkv

Обратите внимание, что нет причин избегать пробелов. Поэтому вы можете упростить свою команду, фактически ничего не меняя в логике регулярных выражений:

rename 's/\./ - /;s/\./ - /;s/\.(?!mkv)/ /g;s/1080p.*(?=.mkv)//g' *.mkv

Тем не менее, это добавляет пробел перед.mkv(ваш оригинал также сделал это ), что вам не нужно. Так что, может быть, вместо этого:

rename -n 's/\./\ -\ /;s/\./\ -\ /;s/\.(?!mkv)/\ /g;s/ 1080p.*(?=.mkv)//g' *.mkv

Если вам нужно более переносимое решение, вы можете просто использовать perlнапрямую (perl доступен почти, но не во всех, *nix-системах):

perl -e 'for (@ARGV){$n=$_;s/1080p.*\.//;s/\.(?!mkv)/ /g;s/S\d+E\d+/- $& -/; rename($n,$_)}' *mkv

И для максимальной переносимости сделайте все это в оболочке (с небольшой частьюsed):

for f in *mkv; do 
    k=${f//./ }
    k=$( printf '%s' "$k" | sed 's/S\([0-9][0-9]*E[0-9][0-9]\)/ - \1 -/')
    k=${k/ 1080p*/.mkv}
    mv -- "$f" "$k"
done

Важное примечание:То, что вы пытаетесь сделать, — очень плохая идея. Наличие пробелов в именах ваших файлов только усложнит вашу жизнь и затруднит любую операцию, которую вы захотите выполнить с этими файлами в будущем. Пожалуйста, пересмотрите.

2
19.03.2021, 02:28

Попробуйте:

rename -v -n \
  's/\./ /g;s/S[X0-9]*E[Y0-9]*/- $& -/;s/ \d*p.* mkv$/.mkv/' *.mkv

Вывод показывает пробный запуск, показывая, что произойдет, но пока не перемещая файлы:

rename(TV.Show.Title.SXEY.Episode.Title.1080p.Uploader.mkv, 
       TV Show Title - SXEY - Episode Title.mkv)

Если вывод выглядит хорошо, удалите -v -n. Поскольку средняяsзамена — это мой специальный способ справиться с маловероятной демонстрационной строкой «SXEY» , (вместо «S02E23» или что-то ),замените это наs/S\d*E\d*/- $& -/:

rename 's/\./ /g;s/S\d*E\d*/- $& -/;s/ \d*p.* mkv$/.mkv/' *.mkv

Примечания:

  • При использовании одинарных кавычек "' '" нет необходимости экранировать пробелы, такие как "\".

  • Приведенный выше код заменяет все .пробелами, затем ищет строку S eason/ E pisode, а затем восстанавливает последнее расширение файла .mkv. Это позволяет избежать необходимости в фиксированных -длинах эпизодов и названий шоу.

1
19.03.2021, 02:28

Не совсем уверен, поддерживаются ли группы захвата в вашей утилите, но их использование было бы жизнеспособной стратегией

([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)[.]([^.]+)

Тогда вы должны заменить на

$1 $2 $3 - $4 - $5 $6.$7

Преимущество этой стратегии заключается в том, что она фактически анализирует семантическое значение вашей другой схемы именования и позволяет переупорядочивать поля или опускать их. Я предпочитаю использовать группы символов для экранирования символов, когда это возможно, легче читать [.], чем \..

0
19.03.2021, 02:28

Причина, по которой я задал этот вопрос, заключается в том, что в заголовке требовалось (лучшее )регулярное выражение.

Но затем я обнаружил, что вы используете переименование, которое, будучи утилитой Perl, использует (вполне разумно )Perl-совместимые регулярные выражения (PCRE ).

Но большинство других переносимых утилит используют другие регулярные выражения (BRE или ERE, обычно ). Эти регулярные выражения не имеют упреждающего просмотра (?=...)или отрицательного упреждающего просмотра (?!...).

Итак, улучшаем регулярное выражение:

$ str='TV.Show.Title.S13E08.Episode.Title.1080p.Uploader.mkv'
$ sed -E 's/\b(S[0-9]{,2}E[0-9]{,2})\b(.*).1080p.Uploader\.(mkv)/- \1 -\2.\3/;s/\./ /g;s/ ([^ ]*)$/.\1/' <<<"$str"
TV Show Title - S13E08 - Episode Title.mkv

Это начинается с использования трех секций захвата:

  • Граница слова (\b), S, за которыми следуют (до )две цифры [0 -9]{,2}, за которыми следуют Eи (до )две цифры, за которыми следует граница слова. Это зафиксирует номера сеансов/эпизодов.
  • Все, что угодно (.*)вплоть до раздела, который нужно удалить.
  • Расширение:\.(mkv)

Re -записывает строку как - \1 -\2.\3.
Затем замените все точки пробелами s/\./ /g. И re -поставьте точку на расширениеs/ ([^ ]*)$/.\1/

Чтобы изменить все файлы, просто выполните простой цикл (независимо от расширения):

ext='.mkv'
for str in./*"$ext"; do
    dst="$(sed -E 's/\b(S[0-9]{,2}E[0-9]{,2})\b(.*)\.1080.*/- \1 -\2/;s/\./ /g' <<<"${str%"$ext"}")$ext"
    echo mv "$str" "$dst"
done

Удалите эхо, если уверены, что оно работает правильно.

0
19.03.2021, 02:28

Теги

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