Mam ogromny plik csv z 10 polami oddzielonymi przecinkami. Niestety niektóre wiersze są zniekształcone i nie zawierają dokładnie 10 przecinków (co powoduje pewne problemy, gdy chcę odczytać plik do R). Jak mogę odfiltrować tylko wiersze zawierające dokładnie 10 przecinków?
9
sed
tutaj) tylko jednego pasowania więcej niż jest to poszukiwane, choć pytanie to robi. Nie powinieneś tego zamykać.grep
odpowiedź nie jest do zaakceptowania dla obu pytań ...Odpowiedzi:
Kolejny POSIX:
Jeśli linia ma 10 przecinków, w tej linii będzie 11 pól. Więc po prostu uczynić
awk
wykorzystania,
jako separatora pól. Jeśli liczba pól wynosi 11, warunekNF == 11
jest spełniony,awk
a następnie wykonuje domyślną akcjęprint $0
.źródło
-F
ustawia separator pól iNF
odnosi się do liczby pól w danym wierszu. Ponieważ{statement}
do warunku nie jest dołączony żaden blok koduNF == 11
, domyślnym działaniem jest wydrukowanie linii. (@cuonglm, jeśli chcesz, dołącz to wyjaśnienie).awk -F , 'NF != 11' <file
-
lub nazwaniem-
.Za pomocą
egrep
(lubgrep -E
w POSIX):Odfiltrowuje to, co nie zawiera 10 przecinków: dopasowuje pełne linie (
^
na początku i$
na końcu), zawierające dokładnie dziesięć powtórzeń ({10}
) sekwencji „dowolna liczba znaków oprócz”, ”, po których następuje pojedynczy„, ”„ (([^,]*,)
), a następnie ponownie dowolna liczba znaków oprócz „,” ([^,]*
).Możesz także użyć
-x
parametru, aby upuścić kotwice:To jest mniej wydajna niż cuonglm „s
awk
rozwiązanie chociaż; ten drugi jest zazwyczaj sześciokrotnie szybszy w moim systemie dla linii z około 10 przecinkami. Dłuższe linie spowodują ogromne spowolnienia.źródło
Najprostszy
grep
kod, który będzie działał:Wyjaśnienie:
-x
zapewnia, że wzór musi pasować do całej linii, a nie tylko jej części. Jest to ważne, aby nie dopasowywać wierszy zawierających więcej niż 10 przecinków.-E
oznacza „rozszerzone wyrażenie regularne”, co powoduje, że w wyrażeniu regularnym występuje mniej ucieczki odwrotnego ukośnika.Nawiasy są używane do grupowania, a
{10}
następnie oznacza, że musi być dokładnie dziesięć dopasowań w rzędzie wzorca w nawiasach.[^,]
jest klasą znaków - na przykład[c-f]
pasuje do każdego pojedynczego znaku, który jest ac
, ad
,e
lub anf
, i[^A-Z]
pasuje do każdego pojedynczego znaku, który NIE jest wielką literą.[^,]
Dopasowuje więc dowolny pojedynczy znak oprócz przecinka.Klasa
*
po znaku oznacza „zero lub więcej z nich”.Zatem część wyrażenia regularnego
([^,]*,)
oznacza „Dowolny znak oprócz przecinka dowolną liczbę razy (w tym zero razy), po którym następuje przecinek” i{10}
określa 10 z nich. Następnie[^,]*
dopasuj resztę znaków niebędących przecinkami do końca wiersza.źródło
To najpierw rozgałęzia dowolny wiersz z 11 lub więcej przecinkami, a następnie drukuje tylko te, które pasują do 10 przecinków.
Najwyraźniej odpowiedziałem na to wcześniej ... Oto plagiat z pytania szukającego dokładnie 4 wystąpień jakiegoś wzorca:
źródło
s/hello/world/2
zs//world/2
GNU sed działać prawidłowo. Z dwomased
z pamiątki,/usr/5bin/posix/sed
podnieś segfault,/usr/5bin/sed
przechodzi w bezokolicznik.sed
iawk
(w komentarzach) - podoba mi się ta odpowiedź i głosowałem za nią, ale zauważam, że tłumaczenie zaakceptowanejawk
odpowiedzi brzmi: „Drukuj wiersze z 11 polami”, a tłumaczenie tejsed
odpowiedzi brzmi: „ Spróbuj usunąć 11. przecinek; w razie niepowodzenia przejdź do następnego wiersza. Spróbuj zamienić 10. przecinek na siebie; wydrukuj wiersz, jeśli ci się powiedzie. ”awk
Odpowiedź daje instrukcje do komputera tak, jak byś je wyrazić w języku angielskim. (awk
jest dobry dla danych w terenie).Rzucając krótkie
python
:Spowoduje to odczytanie każdej linii i sprawdzenie, czy liczba przecinków w linii jest równa 10
line.count(',') == 10
, jeśli tak, wydrukuje to linię.źródło
A oto sposób Perla:
-n
Powodujeperl
czytać swój wiersz po wierszu pliku wejściowego i wykonać skrypt podany przez-e
na każdej linii. Do-a
włącza automatyczną podziału: każda linia wejściowa zostanie podzielona na wartości podanej przez-F
(tu przecinek) i zapisany jako tablicy@F
.$#F
(Lub, bardziej ogólnie$#array
) jest najwyższy wskaźnik tablicy@F
. Ponieważ tablice zaczynają się0
linia z 11 pól będzie mieć@F
od10
. Dlatego skrypt wypisuje wiersz, jeśli ma dokładnie 11 pól.źródło
print if @F==11
ponieważ tablica w kontekście skalarnym zwraca liczbę elementów.Jeśli pola mogą zawierać przecinki lub znaki nowej linii, twój kod musi zrozumieć csv. Przykład (z trzema kolumnami):
Przypuszczam, że większość dotychczasowych rozwiązań odrzuciłaby drugi i czwarty rząd.
źródło