Pertanyaan Pola RegEx untuk membatasi setrip dalam keadaan ini


Skenario

Saya menggunakan perangkat lunak pengubahan nama file pihak ketiga yang ditulis dalam Delphi dan memiliki dukungan pascal-script: http://www.den4b.com/?x=products&product=renamer

Aplikasi ini memungkinkan penggunaan ekspresi reguler untuk mengganti nama file. ini berarti bahwa jika apa yang harus saya lakukan dengan nama file tidak dapat diselesaikan hanya dengan menggunakan satu RegEx, maka saya bisa menggunakan berbagai ekspresi secara bersamaan atau juga kode pascal-script untuk mengakomodasi nama file sampai saya dapat memformat nama file dengan tepat untuk kebutuhan ini pertanyaan atau apa pun ...

Masalah

Saya perlu memformat nama file lagu seperti ini di bawah ini, dalam nama file ini "... menampilkan artis"Bagian di sebelah kanan string, saya harus mencocokkan itu dan posisi di bagian kiri string.

  • Carbin & Sirmark - Maaf Feat. Sevener 
  • Kristjan Cash Cash - Take Me Home Feat. Bebe Rexha (Revoke Remix)

Untuk membuat ini mudah dimengerti, kita bisa membayangkan tokenize nama file seperti ini:

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

Lalu apa yang harus saya lakukan dengan RegEx, adalah format nama file untuk memposisikan token dalam urutan ini:

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

Saya benar-benar melakukannya menggunakan RegEx ini:

\ A ([^ -]?) \ s- \ s * (.?) \ s([([])? ((ft [. \ s] | feat [. \ s] | menampilkan [. \ s]) [^ () {} []] *) ([)]])? +)? \ Z

Mengganti dengan:

$ 1 $ 4 - $ 2 $ 7

Masalahnya dimulai di sini, karena [0]ARTIST dan [2]TRACK token dapat berisi tanda hubung seperti misalnya nama file ini:

  • Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole

Kemudian, koreksi saya jika saya salah, tapi saya pikir itu tidak mungkin untuk menyelesaikan ini dengan cara apa pun, karena mesin tidak dapat memprediksi kapan harus memisahkan satu token untuk yang lain, apa itu nama atau apa yang tidak, karena Saya tidak dapat mengetahui jumlah tanda pisah yang berisi nama file.

Untuk alasan itu, daripada mencari kesempurnaan ingenuos yang bisa menyebabkan buruk   nama file karena jumlah garis di dalamnya, saya lebih suka mencari a   solusi pengecualian nama file, dengan membatasi garis-garis yang berekspresi   harus cocok dengan nama file.

Pertanyaan

Mengambil contoh RegEx yang saya tunjukkan di atas untuk memperluas / memperbaikinya, bagaimana saya bisa mengecualikan nama file yang berisi [0]ARTIST atau sebuah [2]TRACK token dengan tanda hubung?

... Atau dengan kata lain, bagaimana saya dapat memberitahu RegEx saya untuk menghindari memodifikasi nama file ketika nama file berisi lebih dari 1 tanda hubung sebelum "... menampilkan artis"bagian? (bukan setelah)

Pada dasarnya Regex harus menentukan apakah [1]DASH ditemukan lebih dari sekali sebelumnya [3]FEAT_ARTIST, jika ya kemudian kecualikan nama file itu (jangan memodifikasinya)

Saya tahu bagaimana membatasi kemunculan grup Regex kurang lebih seperti ini ([\-]){1} untuk mencocokkan hanya 1 kejadian dasbor, tetapi saya tidak yakin cara menerapkannya dalam ekspresi yang saya gunakan.


hasil yang diharapkan

Hanya beberapa contoh acak ...

Satu dasbor saja sebelum [3]FEAT_ARTISTjadi kita bisa tahu kapan harus berpisah [0]ARTIST dari [2]TRACK token.

  • Dari: 'Carbin & Sirmark - Maaf Feat. Sevener'
  • Untuk: 'Carbin & Sirmark Feat. Sevener - Maaf'

Satu dasbor saja sebelum [3]FEAT_ARTISTjadi kita bisa tahu kapan harus berpisah [0]ARTIST dari [2]TRACK token. Dengan [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{}.

  • Dari: 'Fasilitas Penerbangan - Heart Attack Feat. Owl Eyes (Snakehips Remix)'
  • Untuk: 'Fasilitas Penerbangan Feat. Owl Eyes - Heart Attack (Snakehips Remix)'

Satu dasbor saja sebelum [3]FEAT_ARTISTjadi kita bisa tahu kapan harus berpisah [0]ARTIST dari [2]TRACK token. Dengan [4]POSSIBLE_ADDITIONAL_INFO_INSIDE:()[]{} yang juga mengandung tanda hubung.

  • Dari: 'Fasilitas Penerbangan - Heart Attack Feat. Owl Eyes [Snake - hips Remix]'
  • Untuk: 'Fasilitas Penerbangan Feat. Owl Eyes - Heart Attack [Snake - hips Remix]'

Satu dash hanya di antara [0]ARTIST sebuah [2]TRACK token, tetapi nama file tidak memiliki [3]FEAT_ARTIST jadi kami tidak menyentuhnya.

  • Dari: 'Fedde Le Grand - Cinematic'
  • Untuk: 'Fedde Le Grand - Cinematic'

Satu dash hanya di antara [0]ARTIST sebuah [2]TRACK token, tetapi [3]FEAT_ARTIST sebelum [1]DASH jadi kami tidak menyentuhnya.

  • Dari: 'Fedde Le Grand Feat. Denny White - Sinematik'
  • Untuk: 'Fedde Le Grand Feat. Denny White - Sinematik'

[0]ARTIST memiliki garis putus-putus, jadi kami tidak tahu kapan harus berpisah [0]ARTIST dan [2]TRACK token, jadi Regex harus mengecualikan ini untuk tidak mengubah nama file ini.

  • Dari: 'Artis-Nama - Nama Track feat seseorang'
  • Untuk: 'Artis-Nama - Nama Track feat seseorang'

[2]TRACK memiliki garis putus-putus, jadi kami tidak tahu kapan harus berpisah [0]ARTIST dan [2]TRACK token, jadi Regex harus mengecualikan ini untuk tidak mengubah nama file ini.

  • Dari: 'Nama Artis - Nama-Lacak nama seseorang'
  • Untuk: 'Nama Artis - Nama-Lacak nama seseorang'

[0]ARTIST dan [2]TRACK token memiliki tanda setrip, jadi kami tidak tahu kapan harus memisahkannya, sehingga Regex harus mengecualikan ini untuk tidak mengubah nama file ini.

  • Dari: 'Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole'
  • Untuk: 'Dj E-nergy C-21 - My Super-hero track! feat Dj Ass-hole'

[0]ARTIST dan [2]TRACK token memiliki tanda hubung dan juga [3]FEAT_ARTIST tidak ada, lagi-lagi tidak ada yang bisa dilakukan di sini.

  • Dari: 'Dj E-nergy C-21 - My Super-hero track!'
  • Untuk: 'Dj E-nergy C-21 - My Super-hero track!'

Saya harap ini membantu untuk memahami apa yang saya butuhkan.


4
2017-09-27 12:04


asal


Jawaban:


Coba dengan:

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

DEMO

dan gunakan ganti dengan: $1 Feat.$5 - $2$6

Saya mencobanya dengan ReNamer dan Regex101, dan berfungsi juga jika ada - ( + - + ) dalam nama artis, seperti artist - name, TAPI itu akan gagal jika ada fragmen seperti itu di bagian judul.

Itu ^(.+)\s+-\s+ bagian menggunakan quantifier serakah .+ sebelum space-dash-space, yang dianggap sebagai pembatas antara nama artis dan judul lagu. Jadi itu akan cocok sebanyak mungkin, hingga akhir dari kejadian -, karena itu, ia akan "mengabaikan" garis-garis dengan spasi di nama-nama artis, tetapi itu akan mencocokkan tidak valid, jika elemen tersebut muncul dalam judul lagu. Sehingga:

  • Artist - name - track title feat. someone - itu akan dicocokkan dan dimodifikasi dengan benar,
  • Artist name - track - title feat. someone - Ini akan gagal, sebagai teks akan dibagi pada dasbor terakhir.

Dari pada (ft[.\s]|feat[.\s]|featuring[.\s]) Saya menggunakan [fF](t|eat(uring)?)?\.? yang cocok dengan yang serupa, tetapi harus bekerja lebih cepat (itu harus menahan backtracing sedikit).

di demo saya, ada a + sebagai gantinya \s+ (seperti di atas) karena akan cocok dengan multiline dalam demonstrasi, dan menunjukkan hasil yang tidak valid, tetapi dalam kasus-kasus oneline, seperti dalam masalah Anda, itu akan berfungsi dengan baik.


1
2017-09-30 20:25



Saya pikir satu-satunya hal yang perlu Anda sadari / ubah adalah bahwa ada perbedaan yang dapat dibedakan antara "tanda penghubung" dan "tanda hubung yang melekat". Yaitu tidak ada tanda hubung tertanam yang akan memiliki spasi pada sisi KEDUA (saya harapkan; Anda harus memverifikasi itu). Yang perlu Anda lakukan hanyalah mengubah awal regexp Anda dari atas \A([^-]?)\s-\s* untuk \A(.?)\s-\s+...


1
2017-09-27 19:15



Saya memasukkan semua nama file Anda ke dalam editor teks UltraEdit versi 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!

Dengan string pencarian string reguler Perl

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

dan string pengganti

$1 $3 - $2

nama-nama file itu dimodifikasi dengan case insensitive Menggantikan semua untuk

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!

yang terlihat seperti yang Anda inginkan. UltraEdit menggunakan pustaka ekspresi reguler Boost Perl.

Jika alat penamaan ulang file mendukung juga perilaku lookahead dan kecurangan yang negatif, ekspresi yang mungkin berguna untuk tugas ini adalah:

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

dan string pengganti juga:

$1 $3 - $2

Penjelasan string pencarian:

^ ... memulai garis
\A ... mulai dari penyangga

(.+) -  ... Sebuah serakah ekspresi yang cocok dengan karakter apa pun 1 atau lebih kali (kecuali karakter baris baru) hingga terakhir terjadinya ruangberlariruang dalam kelompok menandai tidak termasuk  -  hasil yang masih dalam pertandingan yang positif untuk seluruh ekspresi.

(.+?)  ... Sebuah tidak tamak ekspresi juga dalam kelompok menangkap yang cocok dengan karakter apa pun (kecuali karakter baris baru) satu atau beberapa kali hingga kejadian selanjutnya dari ruang dan ...

(?:featuring|feat\.?|ft\.?) + ... kata featuring ATAU singkatan feat dengan atau tanpa titik ATAU singkatan ft dengan atau tanpa titik DAN 1 atau lebih spasi.

( ... mulai dari kelompok penangkap ketiga.

(?:[^\r\n (\[{]| (?![(\[{]))+ ... kelompok yang tidak menandai yang cocok juga

  • sebuah karakter tidak makhluk
    • carriage return atau line-feed (UE search string only), atau
    • kurung buka, atau
    • kurung buka persegi, atau
    • sebuah brace pembuka

atau

  • spasi dengan menggunakan ekspresi lookahead negatif memeriksa apakah karakter berikutnya tidak makhluk
    • kurung buka, atau
    • kurung buka persegi, atau
    • sebuah brace pembuka

satu atau beberapa kali. Dengan kata lain, ekspresi terakhir ini cocok dengan semuanya hingga akhir nama file atau ( atau [ atau { tidak termasuk ruang yang tersisa untuk karakter-karakter tersebut untuk menghindari ruangruangberlari setelah FEAT_ARTIST setelah diganti.

) ... akhirnya berakhir kelompok penangkap ketiga.


Edit 1: Juga berfungsi (dalam UltraEdit) adalah string pencarian:

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

yang akan kecuali juga featuring., tetapi membuat ekspresi sedikit lebih mudah.


Edit 2: Juga berfungsi (dalam UltraEdit) adalah string pencarian:

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

yang mengabaikan semua baris yang mengandung dua ruangberlariruang kiri ke FEAT_ARTIST.

Ekspresi ini cocok dengan karakter demi karakter dengan menggunakan lookahead negatif jika string setelah karakter saat ini tidak ruangberlariruang. Ini diperbolehkan untuk kelompok penangkap pertama yang memilih string hingga karakter terakhir yang tersisa pertama ruangberlariruang, tetapi untuk kelompok penangkap kedua seharusnya tidak ada lagi ruangberlariruang karena ini pasti akan menghasilkan hasil negatif untuk seluruh ekspresi.


1
2017-09-27 19:21



Dengan bantuan dari @mcekieraRegex saya memecahkan masalah ini dengan menggunakan skrip pascal yang mencegah penggantian ketika lebih dari satu dasbor ditemukan dalam nama file:

// 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.   

0
2017-10-04 17:49