Шаблон регулярных выражений для ограничения тире в этих обстоятельствах



Сценарий



Я использую стороннее программное обеспечение для переименования файлов, которое написано на Delphi и имеет поддержку Pascal-script: http://www.den4b.com/?x=products&product=renamer



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



Проблема



Мне нужно отформатировать имена файлов песен, как показано ниже, в этих именах файлов "...featuring artist " часть находится справа от строки, Мне нужно сопоставить ее и расположить в левой части строки.





  • Carbin & Sirmark-Извините Подвиг. Севенер


  • Kristjan Cash Cash-Отвези Меня Домой Подвиг. Бебе Рекша (Отозвать Remix)


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



[0]ARTIST   [1]DASH   [2]TRACK   [3]FEAT_ARTIST   [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}


Тогда то, что мне нужно сделать с регулярным выражением, - это отформатировать имя файла для размещения токенов в следующем порядке:



[0]ARTIST   [3]FEAT_ARTIST   [1]DASH   [2]TRACK   [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}


Я действительно делаю это, используя это регулярное выражение:




A([^-]?)s -s*(.?) s([([])?((футовый[.s] / подвиг[.с]|с[.s])[^(){}[]]*)([)]])?(.+)?Z




Замена с:




$1 $4 - $2$7




Проблема начинается здесь, потому что маркеры [0]ARTIST и [2]TRACK могут содержать тире, как, например, это имя файла:





  • Dj E-nergy C-21-мой супер-герой трек! feat Dj Ass-hole


Тогда поправьте меня, если я ошибаюсь, но я думаю, что это просто невозможно решить каким-либо образом, потому что машина не может предсказать, когда отделить один токен от другого, что является именем, а что нет, потому что я не могу знать число тире, содержащее имя файла.

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


Вопрос



Взяв в качестве примера регулярное выражение, которое я показал выше, чтобы расширить / улучшить его, как я мог бы исключить имена файлов, которые содержат [0]ARTIST или an [2]TRACK маркеры с тире?



...Или другими словами, как я могу сказать своему регулярному выражению, чтобы избежать изменения имени файла, когда имя файла содержит более 1 тире Перед "...featuring artist " часть? (не после)



В основном регулярное выражение должно определять, встречается ли [1]DASH более одного раза до [3]FEAT_ARTIST, если да, то исключите это имя файла (не изменяйте его)



Я знаю, как ограничить появление группы регулярных выражений чем-то более или менее подобным этому ([-]){1}, чтобы соответствует только 1 тире вхождения, но я не уверен, как реализовать его в выражении, которое я использую.





Ожидаемые Результаты



Просто несколько случайных примеров...



Один тире только перед [3]FEAT_ARTIST, так что мы можем знать, когда отделить [0]ARTIST от [2]TRACK маркеров.




  • От: ' Carbin & Sirmark - Извините Подвиг. Севенер '

  • To: ' Carbin & Sirmark Feat. Sevener-Sorry '


Один тире только перед [3]FEAT_ARTIST, так что мы можем знать, когда отделите [0]ARTIST от [2]TRACK токенов. С [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}.




  • От: 'Летное Оборудование - Инфаркт Feat. Совиные Глаза (Snakehips Remix)'

  • To: ' Flight Facilities Feat. Совиные Глаза-Сердечный Приступ (Snakehips Remix)'


Один тире только перед [3]FEAT_ARTIST, так что мы можем знать, когда отделить [0]ARTIST от [2]TRACK маркеров. С [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{} , который также содержит тире.




  • От: 'Летное Оборудование - Инфаркт Feat. Совиные глаза [змея-бедра Ремикс]'

  • To: ' Flight Facilities Feat. Совиные глаза-сердечный приступ [змея-бедра ремикс]'


Один тире только между [0]ARTIST и [2]TRACK маркерами, но имя файла не имеет [3]FEAT_ARTIST, поэтому мы его не трогаем.




  • Из: 'Fedde Le Grand-Cinematic '

  • To: 'Fedde Le Grand-Cinematic '


Один тире только между [0]ARTIST и [2]TRACK знаками, но [3]FEAT_ARTIST находится перед [1]DASH, поэтому мы не касаемся оно.




  • Из: 'Fedde Le Grand Feat. Денни Уайт-Кинематографический '

  • To: 'Fedde Le Grand Feat. Денни Уайт-Кинематографический '


[0]ARTIST имеет тире, поэтому мы не можем знать, когда разделять маркеры [0]ARTIST и [2]TRACK, поэтому регулярное выражение должно исключить это, чтобы не изменять это имя файла.




  • From: 'имя исполнителя-название трека feat someone '

  • To: 'имя исполнителя-название трека feat someone '


[2]TRACK имеет тире, поэтому мы не можем знать, когда разделять маркеры [0]ARTIST и [2]TRACK, поэтому регулярное выражение должно исключить это, чтобы не изменять это имя файла.




  • от: 'имя исполнителя-трек-Имя feat someone '

  • To: 'имя исполнителя-трек-Имя feat someone '


[0]ARTIST и [2]TRACK токены имеют тире, поэтому мы не можем знать, когда их разделять, поэтому регулярное выражение должно исключить это, чтобы не изменять это имя файла.




  • от: 'Dj E-nergy C-21-My Супер-герой трек! feat Dj Ass-hole '

  • To: 'Dj E-nergy C-21-мой трек Super-hero! feat Dj Ass-hole '


[0]ARTIST и [2]TRACK токенов имеет тире, а также [3]FEAT_ARTIST не существует, опять же здесь нечего делать.




  • из: 'Dj E-nergy C-21 - мой трек Super-hero! '

  • To: 'Dj E-nergy C-21-мой трек Super-hero! '


Я надеюсь, что это поможет понять, что мне нужно.
847   4  

4 ответов:

Попробуйте с:

^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$

Демо

И использовать заменить на: $1 Feat.$5 - $2$6

Я пробовал его с ReNamer и Regex101, и он также работает, если есть - ( + - + ) in artist name, like artist - name, но он потерпит неудачу, если в заглавной части будет такой фрагмент.

Часть ^(.+)\s+-\s+ использует жадный Квантор .+ перед последовательностью пробел-тире-пробел, который рассматривается как разделитель между именем исполнителя и названием трека. Так что он будет соответствовать столько, сколько он может, вплоть до последнего появления -, из-за этого он будет "игнорировать" тире с пробелами в именах исполнителей, но это будет недопустимое совпадение, если такой элемент встречается в названии трека. Итак:

  • Artist - name - track title feat. someone - он будет соответствовать и исправлено должным образом,
  • Artist name - track - title feat. someone - он провалится, как текст будет разбит на последнем тире.

Вместо (ft[.\s]|feat[.\s]|featuring[.\s]) я использовал [fF](t|eat(uring)?)?\.?, которые совпадают с аналогичными, но должны работать быстрее (это должно немного сдерживать отступление).

В моем демо есть + вместо этого \s+ (Как и выше), поскольку он будет соответствовать многострочным в демонстрации и показывать недопустимые результаты, но в oneline случаях, как и в вашей задаче, он должен работать нормально.

Я думаю, что единственное, что вам нужно понять/изменить, - это то, что существует различимая разница между "разделительным дефисом" и "встроенными дефисами". А именно, ни один из встроенных дефисов не будет иметь пробелов с обеих сторон (я ожидаю; вам нужно будет это проверить). Все, что вам нужно сделать, это изменить начало вашего регулярного выражения выше с \A([^-]?)\s-\s* на \A(.?)\s-\s+...

Я поместил все ваши имена файлов в текстовый редактор UltraEdit версии 22.10:

Carbin & Sirmark - Sorry Feat. Sevener
Kristjan Cash Cash - Take Me Home Feat. Bebe Rexha (Revoke Remix)
Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole
Flight Facilities - Heart Attack Feat. Owl Eyes (Snakehips Remix)
Flight Facilities - Heart Attack Feat. Owl Eyes [Snake--hips Remix]
Fedde Le Grand - Cinematic
Fedde Le Grand Feat. Denny White - Cinematic
Artist-Name - Track Name feat someone
Artist Name - Track-Name feat someone
Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole
Dj E-nergy C-21 - My Super-hero track!

С помощью строки поиска регулярных выражений Perl

^(.+) - (.+?) ((?:featuring|feat\.?|ft\.?) +(?:[^\r\n (\[{]| (?![(\[{]))+)

И строка замены

$1 $3 - $2

Эти имена файлов были изменены с учетом регистра заменить все на

Carbin & Sirmark Feat. Sevener - Sorry
Kristjan Cash Cash Feat. Bebe Rexha - Take Me Home (Revoke Remix)
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
Flight Facilities Feat. Owl Eyes - Heart Attack (Snakehips Remix)
Flight Facilities Feat. Owl Eyes - Heart Attack [Snake--hips Remix]
Fedde Le Grand - Cinematic
Fedde Le Grand Feat. Denny White - Cinematic
Artist-Name feat someone - Track Name
Artist Name feat someone - Track-Name
Dj E-nergy C-21 feat Dj Ass-hole - My Super-hero track!
Dj E-nergy C-21 - My Super-hero track!

Похоже, это то, что вам нужно. UltraEdit использует библиотеку регулярных выражений Boost Perl.

Если файл переименовать инструмент также поддерживает негативное заглядывание вперед и жадное сопоставление поведение, выражение, возможно, полезное для этой задачи:

\A(.+) - (.+?) ((?:featuring|feat\.?|ft\.?) +(?:[^ (\[{]| (?![(\[{]))+)

И строка замены также:

$1 $3 - $2

Объяснение строки поиска:

^ ... начало строки
\A ... начало буфера

(.+) -  ... a жадное выражение, которое соответствует любому символу 1 или более раз (кроме символов новой строки) до последнего появления пространстваДашпространство в маркирующей группе не включая  - , что приводит к положительному совпадению для всего выражения.

(.+?)  ... выражение не жадное также в группе захвата, совпадающей с любым символом (кроме символов новой строки) один или несколько раз до следующего вхождения пробела И...

(?:featuring|feat\.?|ft\.?) + ... слово featuring или аббревиатура feat с точкой или без точки или аббревиатура ft с точкой или без точки и 1 или более пробелов.

( ... начало третьего захвата группа.

(?:[^\r\n (\[{]| (?![(\[{]))+ ... группа без маркировки, соответствующая любому

  • символ Не бытие
    • возврат каретки или перевод строки (только строка поиска UE), или
    • открывающая скобка, или
    • открывающая квадратная скобка, или
    • открывающая скобка

Или

  • пробел с использованием отрицательного выражения lookahead, проверяющего, является ли следующий символ Не
    • открытие скобки, или
    • открывающая квадратная скобка, или
    • открывающая скобка

Один или несколько раз. Другими словами, это последнее выражение соответствует всему, вплоть до конца имени файла или ( или [ или {, не включая пробел, оставленный этим символам, чтобы избежать получения пробелакосмостире после FEAT_ARTIST после замены.

) ... наконец заканчивается третий захват группы.


Edit 1: Также Рабочая (в UltraEdit) строка поиска:

^(.+) - (.+?) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)

, что было бы также featuring., но делает выражение немного проще.


Edit 2: также работает (в UltraEdit) строка поиска:

^((?:.(?! - ))+.) - ((?:.(?! - ))+) ((?:featuring|feat|ft)[ .]+(?:[^\r\n (\[{]| (?![(\[{]))+)

Который игнорирует все строки, содержащие два пробелаДашпробел слева до FEAT_ARTIST.

Это выражение соответствует символу за символом с использованием отрицательного lookahead, если строка после текущего символа не является пространствоДашпространство . Это разрешено для первой группы захвата, которая выбирает строку до последнего символа слева от первого пробелаДашпространство , но для второй группы захвата не должно быть больше пространства . Дашпробел , поскольку это определенно приведет к отрицательному результату для всего выражения.

С помощью регулярного выражения @m. cekiera я решил эту задачу с помощью скрипта pascal, который предотвращает любую замену, когда в имени файла найдено более одного тире:

// Formats an audio filename that has the "...featuring artist" part at the end of filename.
//------------------------------------------------------------------------------------------


// Pseudo-Example:
//
// From: [0]ARTIST_NAME  [1]DASH  [2]TRACK_TITLE  [3]FEAT_ARTIST  [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}
// To:   [0]ARTIST_NAME  [3]FEAT_ARTIST  [1]DASH  [2]TRACK_TITLE  [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}

// Real-Example:
//
// From: Carbin & Sirmark - Sorry Feat. Sevener.mp3
// To:   Carbin & Sirmark Feat. Sevener - Sorry.mp3

// Known limitations:
//
// • If [0]ARTIST_NAME or [2]TRACK_TITLE parts contains any " - " the script will not work properlly.
//   By default the script prevents any replacement on that kind of filenames, so don't worry.


var
  rgxPattern: string;
  rgxReplace: string;
  dashCount: integer;
  baseName: string;
  extension: WideString;

begin

  baseName  := WideExtractBaseName(FileName)
  extension := WideExtractFileExt(FileName);

  // The regular expression that matches the filename parts.
  // http://stackoverflow.com/questions/32807698/regex-pattern-to-limit-dashes-in-these-circumstances
  rgxPattern := '^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$'
  rgxReplace := '$1 Feat.$5 - $2$6'

  // The amount of " - " that contains the filename.
  dashCount := high(MatchesRegEx(baseName, '\s-\s' , false));

  // If only one " - " is found then...
  If (dashCount = 0) Then
    begin // Do the replacement.
      baseName := ReplaceRegEx(baseName, rgxPattern, rgxReplace, false, true)
      FileName := baseName + extension;
    end;

end.   

Comments

    Ничего не найдено.