Jestem nowy, aby zmienić i próbuję wziąć teksty piosenek i izolować tytuły wiersza, podkładowe wokale i główne wokale:

Oto przykład niektórych tekstów:

[Intro]
D.A. got that dope!

[Chorus: Travis Scott]
Ice water, turned Atlantic (Freeze)
Nightcrawlin' in the Phantom (Skrrt, Skrrt)...

Tytuły wiersza obejmują wsporniki kwadratowe i wszelkie słowa między nimi. Mogą być pomyślnie odizolowane

r'\[{1}.*?\]{1}'

Wokale podkładowe są podobne do tytułów wierszy, ale między (). Zostali z powodzeniem wyizolowanych z:

r'\({1}.*?\){1}'

Dla głównych wokalów użyłem

r'\S+'

Który wyizoluje główne_wokals, ale także tytuły wiersza i podkładu wokalu. Nie mogę dowiedzieć się, jak wyizolować tylko główne wokale z prostą res.

Oto skrypt Pythona, który dostaje pragnienie wyjścia, ale chciałbym to zrobić z RES (jako ćwiczenie uczenia się) i nie może tego zrozumieć poprzez dokumentację.

import re

file = 'D:/lyrics.txt'
with open(file, 'r') as f:
    lyrics = f.read()

def find_spans(pattern, string):
    pattern = re.compile(pattern)
    return [match.span() for match in pattern.finditer(string)]

verses = find_spans(r'\[{1}.*?\]{1}', lyrics)
backing_vocals = find_spans(r'\({1}.*?\){1}', lyrics)
main_vocals = find_spans(r'\S+', lyrics)

exclude = verses
exclude.extend(backing_vocals)

not_main_vocals = []
for span in exclude:
    start, stop = span
    not_main_vocals.extend(list(range(start, stop)))

main_vocals_temp = []
for span in main_vocals:
    append = True
    start, stop = span
    for i in range(start, stop):
        if i in not_main_vocals: 
            append = False
            continue
    if append == True: 
        main_vocals_temp.append(span)
main_vocals = main_vocals_temp
3
Osuynonma 22 luty 2019, 17:53

2 odpowiedzi

Najlepsza odpowiedź

Wypróbuj to Demo:

pattern = r'(?P<Verse>\[[^\]]+])|(?P<Backing>\([^\)]+\))|(?P<Lyrics>[^\[\(]+)'

Możesz użyć re.finditer, aby wyizolować grupy.

breakdown = {k: [] for k in ('Verse', 'Backing', 'Lyrics')}
for p in pattern.finditer(song):
    for key, item in p.groupdict().items():
        if item: breakdown[key].append(item)

Wynik:

{
  'Verse': 
    [
      '[Intro]', 
      '[Chorus: Travis Scott]'
    ], 
  'Backing': 
    [
      '(Freeze)', 
      '(Skrrt, Skrrt)'
    ], 
  'Lyrics': 
    [
      '\nD.A. got that dope!\n\n', 
      '\nIce water, turned Atlantic ', 
      "\nNightcrawlin' in the Phantom ", 
      '...'
    ]
}

Aby rozwinąć nieco dalej na wzorze, używa nazwanych grup, aby oddzielić trzy różne grupy. Korzystanie z [^\]+] i podobnie oznacza znalezienie wszystkiego, co jest nie ] (i podobnie, gdy \) oznacza wszystko nie {{x3 }}). W części tekstu wykluczamy wszystko, co zaczyna się od [ i (. Link do demo na REGEX101 wyjaśniłby komponenty w więcej szczegółów, jeśli potrzebujesz.

Jeśli nie obchodzi cię na Newlines w głównych słowach, użyj (?P<Lyrics>[^\[\(\n]+) (co obejmuje \n), aby zmienić teksty bez Newlines:

'Lyrics': [
  'D.A. got that dope!', 
  'Ice water, turned Atlantic ',
  "Nightcrawlin' in the Phantom ", 
  '...'
]
1
r.ook 22 luty 2019, 15:39

Możesz szukać tekstu między nawiasami zamętnymi a open-nawiasami, używając grup REGEX. Jeśli masz jedną grupę (pod-wzorzec wewnątrz rundy) w REGEX, Re.findall zwróci zawartość tych nawiasów.

Na przykład "\[(.*?)\]" znajdzie cię tylko etykiety sekcji, nie zawierające nawiasów kwadratowych (ponieważ są poza grupą).

Regex "\)(.*?)\(" znaleziono tylko ostatnią linię ("Nóżngrawiał" w fantomach ").
Podobnie możemy znaleźć pierwszą linię z "\](.*?)\[".

Łącząc dwa rodzaje wsporników w klasę znaków, (znacząco messier wygląda) regex "[\]\)](.*?)[\[\(]" przechwytuje wszystkie teksty.

Będzie tęsknić za liniami, które nie mają wsporników przed lub po nich (tj. Samo początek przed [Intro], jeśli są jakieś, czy na końcu, jeśli nie ma późniejszych wokalistów). Możliwym obejściem jest przygotowanie znaku "]" i dołączyć znak "[" do końca, aby wymyślił dopasowanie do uruchomienia / końca na końcu ciągu. Uwaga Musimy dodać opcję Dotall, aby upewnić się, że Wildcard "." pasuje do znaku nowej linii "n"

import re

lyrics = """[Intro]
D.A. got that dope!

[Chorus: Travis Scott]
Ice water, turned Atlantic (Freeze)
Nightcrawlin' in the Phantom (Skrrt, Skrrt)..."""


matches = re.findall(r"[\]\)](.*?)[\[\(]", "]" + lyrics + "[", re.DOTALL)
main_vocals = '\n'.join(matches)
1
Joe Teague 22 luty 2019, 15:32