2010-12-18 11 views
7

Witam ekspertów wyrażenie regularneWyrażenia regularne - jak zastąpić znak w cudzysłowie

nigdy nie było problemem manipulacji ciąg nie mogę rozwiązać z wyrażeń regularnych do tej pory, przynajmniej w elegancki sposób za pomocą tylko jednego krok. Oto przykładowe dane pracuję z:.

0 „sekcja1”, "(7) Dostawa «świadectwo»poza granicami Stanów Zjednoczonych zabronione Ponieważ zarówno sekcji 339 statutu 1940, 68/a odcinek 341 niniejszej ustawy są wyraźny w swoim oświadczeniu, że certyfikat będą dały obywatela, tylko jeśli taka osoba jest w czas w Stanach Zjednoczonych, to jest jasne, że dokument ten nie może i nie można ich dostarczyć poza teren Stanów Zjednoczonych . ", Http: //www.google.co m/

1 "sekcja2" ,, http: //www.google.com/

2 "sekcja3", ",,", http: //www.google.com/

To jest sekcja znacznie większego pliku CSV. Z jednym eleganckim wyrażeniem regularnym chciałbym zastąpić tylko wszystkie przecinki występujące w podwójnych cudzysłowach znakiem podkreślenia (_). Ważne jest, aby wyrażenie regularne NIE zastępowało przecinków poza cudzysłowami, ponieważ mogłoby to zepsuć strukturę danych CSV.

Dzięki, Tom

-

Wyjaśnienie:

Sorry chłopaki, wysłałem pytanie bez pełnego wyjaśnienia mojej sytuacji, więc pozwól mi podsumować następująco:

  • Przyjmijmy że cytaty w cudzysłowie są już zmienione (cytaty w cudzysłowach w pliku CSV zapisanym przez Excela są reprezentowane przez "" lub """ itd., Więc można je łatwo wymienić wcześniej).
  • Pracuję w JavaScript.

Korzystanie z przykładowy tekst powyżej, tutaj jest to, co powinno wyglądać po uruchomieniu zastąpienie wyrażenia regularne (nie powinno być w sumie 5 zamienniki):

0 „sekcja1”, "(7) Dostawa „świadectwo” poza Stanami Zjednoczonych zabronione. Ponieważ zarówno sekcji 339 1940 statute_ 68/i odcinek 341 niniejszej ustawy są wyraźny w swoim oświadczeniu, że certyfikat będą dały citizen_ tylko jeśli takie indi indywidualnej, jest czas w Stanach States_ to jest jasne, że dokument ten nie mógł i nie mogą być dostarczane poza Stanów Zjednoczonych „http: //www.google.com/

1”. sekcja2 ",, http: //www.google.com/

2 "sekcja3", "__", http: //www.google.com/

+1

W jaki sposób unikniesz cytatów z cytatów? –

+0

@Assaf, dobre pytanie; zobacz moje wyjaśnienie powyżej. – 10basetom

Odpowiedz

12

Pomogę ci, ale musisz obiecać, że przestaniesz używać słowa "elegancki". Ostatnio pracowało zbyt ciężko i zasługuje na odpoczynek. : P

(?m),(?=[^"]*"(?:[^"\r\n]*"[^"]*")*[^"\r\n]*$) 

Dopasowuje przecinek, jeżeli między przecinkiem a końcem zapisu, jest nieparzysta liczba cudzysłowie. Zakładam standardowy format CSV, w którym rekord kończy się na następnym separatorze linii, który nie jest ujęty w cudzysłowy. Separatory linii są legalne w cytowanych polach, podobnie jak w cudzysłowach, jeśli są one poprzedzone inną kwotą.

W zależności od tego, jaki smak regexu używasz, konieczne może być użycie \r?$ zamiast tylko $. W .NET na przykład tylko linia (\n) jest traktowana jako separator linii. Ale w Javie $ pasuje przed \r w \r\n, ale nie między \r i \n (chyba że ustawisz tryb UNIX_LINES).

+0

Alan Moore, jesteś ekspertem od ekspresji regularnej :-). Spośród wszystkich rozwiązań, które otrzymałem tutaj (i gdzie indziej), twoje jedyne super regularne wyrażenie było w stanie zrobić dokładnie to, co opisałem w moim pytaniu, jeszcze zanim napisałem wyjaśnienie. Punkty premiowe i TAK twoje rozwiązanie jest "eleganckie" w porównaniu do rozwiązania, które chciałbym wymyślić (wymagające wielu wyrażeń regularnych i tablicy do tymczasowego przechowywania). – 10basetom

+0

@Alan, użyłem twojego zwykłego wyrażenia, jak to jest, z wyjątkiem tego, że pominąłem?: - czy jest inne zastosowanie oprócz zapamiętywania pojedynku? – 10basetom

+0

@ 10basetom: W wielu smakach regex, jeśli używasz grup przechwytywania w wyrażeniu regularnym podzielonym, to, co zrobią, zostanie dodane do wyników wraz ze zwykłymi tokenami. Ale przyznaję, że nawet o tym nie myślałem. Po prostu podążałem za regułą: nigdy nie używaj grupy przechwytującej, jeśli grupa niezapisująca może wykonać to zadanie. Każda dodatkowa grupa przechwytująca dodaje nieco więcej do narzutu zasobów, zarówno sprzętu, jak i oprogramowania typu wetware (to znaczy, trudniej jest autorowi śledzić, która grupa przechwytuje co). –

3

Wyrażenia regularne nie są szczególnie dobre na dopasowanie wyważony tekst (czyli początkowy i końcowy cytaty).

naiwne podejście byłoby wielokrotnie zastosować coś takiego (aż nie pasuje):

s/(^[^"]*(?:"[^"]*"[^"]*)*?)"([^",]*),([^"]*)"/$1"$2_$3"/ 

Ale to nie będzie działać ze zbiegłych cytatów. Najlepsze (tj. Najprostsze, najłatwiejsze do odczytania i najłatwiejsze w obsłudze) rozwiązanie to: użyj parsera pliku CSV, przechodź kolejno przez wszystkie wartości pól (zastępując przecinki podkreśleniami), a następnie zapisz je z powrotem do plik.

0

Przepraszam, jeśli nie używasz Pythona, w którym jest następujący kod. Nie widzę żadnego wskazania, którego języka używasz. W każdym razie myślę, że kod jest całkowicie zrozumiały.

import re 

ch = '''0,"section1","(7) Delivery of 'certificate' outside the United States prohibited. 
Since both section 339 of the 1940 statute, 68/ and section 341 of the present law are explicit 
in their statement that the certificate shall be furnished the citizen, only if such individual 
is at the time within the United States, it is clear that the document could not and cannot be 
delivered outside the United States.",http://www.google.com/ 

1,"section2",,http://www.google.com/ 

2,"section3",",,",http://www.google.com/ 
''' 

poto = re.compile('("[^"]+")') 

def comma_replacement(match): 
    return match.group().replace(',','_') 

print poto.sub(comma_replacement , ch) 

Metoda ta utrzymuje 2 sąsiednie przecinki linii

1 "sekcja2" ,, http: //www.google.com/

niezmienione. Czy jest to właściwe, czego chcesz?

Powiązane problemy