Шаблон регулярных выражений для ограничения тире в этих обстоятельствах
Сценарий
Я использую стороннее программное обеспечение для переименования файлов, которое написано на 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! '
Я надеюсь, что это поможет понять, что мне нужно.
4 ответов:
Попробуйте с:
^(.+)\s+-\s+(.+?)\s+[fF](t|eat(uring)?)?\.?([^([\])\n]+)(.+)?$И использовать заменить на:
$1 Feat.$5 - $2$6Я пробовал его с ReNamer и Regex101, и он также работает, если есть
-(+-+) in artist name, likeartist - 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