Mam dość duży plik CSV (75 MB). Po prostu próbuję stworzyć jego wykres, więc naprawdę nie potrzebuję wszystkich danych.
Rewording: Chciałbym usunąć n linii, następnie zachować jedną linię, następnie n usunąć linie i tak dalej.
Więc jeśli plik wyglądał tak:
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
i n = 2, to wynik będzie:
Line 3
Line 6
Wygląda sed
na to, że mógłbym to zrobić, ale nie byłem w stanie dowiedzieć się, jak to zrobić. Polecenie bash byłoby idealne, ale jestem otwarty na każde rozwiązanie.
Odpowiedzi:
NR
(liczba rekordów) zmienna jest liczbą rekordów, ponieważ domyślnym zachowaniem jest nowa linia dlaRS
(separator rekordów). wzorzec i akcja są opcjonalne w domyślnym formacie awk'pattern {actions}'
. kiedy dajemy tylko część wzoru,awk
zapisuje wszystkie pola$0
dlatrue
warunków naszego wzoru .źródło
awk 'NR == 1 || NR % 3 == 0'
awk 'NR == 1 || NR % 2 == 0' myfile.txt | wc -l
wynik nieparzystej liczby, podczas gdy oryginalny plik miał parzystą liczbę wierszy. Odpowiedź @kev działa najlepiej w moim przypadku testowym.sed
może również to zrobić:man sed
wyjaśnia~
jako:źródło
1p
drukuje pierwszą linię,0~3p
drukuje co trzecią linię, zaczynając od linii 3 (1p
jest to zatem wymagane, aby wydrukować linię 1). Pamiętaj jednak, że0~3
nie jest to standard, ale rozszerzenie GNU sed.sed -n '1p;0~10p' '.\in.txt' > out.txt
aby wydrukować zredukowany plik do pliku wyjściowego.Perl też może to zrobić:
Ten program wypisze pierwszy wiersz swojego wejścia, a następnie co trzeci wiersz.
Aby to trochę wyjaśnić,
<>
to operator wprowadzania linii, który iteruje po liniach wprowadzania, gdy jest używany w takiejwhile
pętli. Zmienna specjalna$.
zawiera liczbę odczytanych do tej pory wierszy i%
jest operatorem modułu.Ten kod można zapisać jeszcze bardziej kompaktowo jako jeden wiersz, używając przełączników
-n
i-e
:-e
Wyłącznik przyjmuje część kodu Perl wykonać jako parametr linii polecenia, podczas gdy-n
przełącznik pośrednio owija kodu wwhile
pętli, jak pokazany powyżej.Edit: rzeczywiście dostać linii 1, 3, 6, 9, ... jak w tym przykładzie, zamiast linii 1, 4, 7, 10, ..., jak po raz pierwszy przyjęto chciał wymienić
$. % 3 == 1
się$. == 1 or $. % 3 == 0
.źródło
Jeśli chcesz to zrobić za pomocą skryptu Bash , możesz spróbować:
Zapisz go jako „read_lines.sh” i pamiętaj, aby dać + x uprawnienia do pliku bash.
źródło
./read_lines.sh > new_file.txt
.Rozwiązaniem w czystym bashu, które nie odradza procesu jest:
Pierwszy wiersz pomija 2 linie na początku pliku, a następnie
while
drukuje następny wiersz i ponownie pomija 2 linie.Jeśli twój plik jest mały, jest to bardzo wydajny sposób wykonania zadania, ponieważ nie uruchamia procesu. Gdy plik jest duży,
sed
należy go użyć, ponieważ jest bardziej wydajny w przetwarzaniu iobash
.źródło
Wersja Python (zarówno Python 2, jak i Python 3):
zamień na parametry
[::3]
początkowe, końcowe i krokowe, aby uzyskać większą kontrolę. Np.[10:36:5]
Wypisuje linie 10,15, ..., 35.Uwaga: ponieważ
readlines()
zachowuje zakończenia linii, wynik tego wywołania może kończyć się pustą ostatnią linią, chyba że pierwotna ostatnia linia zostanie wyparta przez wybrany rozmiar kroku.Możliwa jest również wersja strumienia (tutaj wyjście tylko po zakończeniu strumienia):
źródło