W pliku tekstowym chcę usunąć ,
(przecinki), a także "
(cudzysłowy) (tylko jeśli podwójne cudzysłowy zawierają liczby oddzielone przecinkami).
56,72,"12,34,54",x,y,"foo,a,b,bar"
Oczekiwany wynik
56,72,123454,x,y,"foo,a,b,bar"
Uwaga: powyższą linię pokazuję tylko jako przykład. Mój plik tekstowy zawiera wiele wierszy, jak wyżej, a liczby oddzielone przecinkami w podwójnych cudzysłowach powinny się różnić. To jest,
56,72,"12,34,54",x,y,"foo,a,b,bar"
56,92,"12,34",x,y,"foo,a,b,bar"
56,72,"12,34,54,78,76,54,67",x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar","12,34,54"
56,72,x,y,"foo,a,b,bar","12,34,54","45,57,84,92","bar,foo"
Oczekiwany wynik:
56,72,123454,x,y,"foo,a,b,bar"
56,92,1234,x,y,"foo,a,b,bar"
56,72,12345478765467,x,y,"foo,a,b,bar"
56,72,x,y,"foo,a,b,bar",123454
56,72,x,y,"foo,a,b,bar",123454,45578492,"bar,foo"
W n
podwójnych cudzysłowach jest wiele liczb oddzielonych przecinkami. A także pozostaw podwójne cudzysłowy, które zawierają znaki w niezmienionej postaci.
Uwielbiam sed
narzędzie do przetwarzania tekstu. Cieszę się, jeśli opublikujesz jakieś sed
rozwiązanie tego problemu.
text-processing
sed
csv
Avinash Raj
źródło
źródło
56,72,"12,34,54",x,y,"foo,a,b,bar"
do56,72,123454,x,y,"a,b"
,foo
abar
znaczy zniknąć. Czy to twoja pożądana wydajność?foo
ibar
) są usuwane wraz z przecinkami. Ponadto niektóre cytaty znikają tam, gdzie pozostają inne. Nie wspominając, że przecinki międzya
ib
pozostają również. Czy jest w tym jakiś wzór?Odpowiedzi:
To (zaadaptowane stąd ) powinno zrobić to, czego potrzebujesz, chociaż Perl @ rici jest o wiele prostszy:
Wyjaśnienie
:a
: zdefiniuj etykietę o nazwiea
.s/(("[0-9,]*",?)*"[0-9,]*),/\1/
: Ten trzeba rozbić(foo(bar))
,\1
będziefoobar
i\2
będziebar
."[0-9,]*",?
: dopasuj 0 lub więcej z0-9
lub,
, a następnie 0 lub 1,
.("[0-9,]*",?)*
: dopasuj 0 lub więcej z powyższych."[0-9,]*
: dopasuj 0 lub więcej0-9
lub,
które pojawiają się zaraz po"
ta;
: wróć do etykietya
i uruchom ponownie, jeśli podstawienie się powiodło.s/""/","/g;
: przetwarzanie końcowe. Wymień""
się","
.s/"([0-9]*)",?/\1,/g
: usuń wszystkie cudzysłowy wokół liczb.Można to łatwiej zrozumieć na innym przykładzie:
Tak więc, podczas gdy możesz znaleźć liczbę, która jest tuż po cytacie, po której następuje przecinek i inny numer, połącz dwie liczby razem i powtarzaj proces, aż nie będzie to już możliwe.
W tym momencie uważam, że warto wspomnieć o cytacie z
info sed
tego, który pojawia się w sekcji opisującej zaawansowane funkcje, takie jak etykieta użyta powyżej (dzięki za znalezienie if @Braiam):źródło
Jeśli perl jest w porządku, oto krótki (i prawdopodobnie szybki, jeśli niekoniecznie prosty :)) sposób:
e
Flag dos:::
operatora (co jest tylko kolejnym sposobem na piśmies///
) powoduje zastąpienie być traktowane jako wyraz, który jest oceniany za każdym razem. Wyrażenie to pobiera wyrażenie$1
z wyrażenia regularnego (w którym już brakuje cudzysłowów) i tłumaczy (y///
które można również zapisać jakotr///
), usuwając (/d
) wszystkie przecinki.r
Flagęy
jest konieczne w celu uzyskania wartości będzie przetłumaczony łańcuch zamiast liczby tłumaczeń.Dla tych, którzy w jakiś sposób czują się przygnębieni przez perla, oto odpowiednik python. Python tak naprawdę nie jest narzędziem powłoki jednowierszowej, ale czasami można go przekonać do współpracy. Poniższe można zapisać jako jedną linię (w przeciwieństwie do
for
pętli, które nie mogą być), ale przewijanie w poziomie sprawia, że (jeszcze bardziej) jest nieczytelny:źródło
y///
zamiasttr///
uratować nam jeszcze jedną postać.W przypadku danych CSV użyłbym języka z prawdziwym analizatorem składni CSV. Na przykład z Ruby:
źródło
Cześć Oto kod Pythona , który zastępuje przecinki podwójnymi cudzysłowami, przecinki są zastępowane znakiem potoku (|)
Ten kod Pythona ma zastępować przecinki ujęte w podwójne cudzysłowy
np .: x, y, z, 1,2, „r, e, t, y”, h, 8,5,6
jeśli zastąpić Rura x, y, z, 1,2, „r | e | t | y”, h, 8,5,6
jeśli zamień na null x, y, z, 1,2, „rety”, h, 8,5,6
źródło