Mam zrzut SQL ~ 23000 wierszy zawierający dane o wartości kilku baz danych. Muszę wyodrębnić pewną sekcję tego pliku (tj. Dane dla pojedynczej bazy danych) i umieścić ją w nowym pliku. Znam zarówno numer początkowy, jak i końcowy danych, które chcę.
Czy ktoś zna polecenie uniksowe (lub serię poleceń), aby wyodrębnić wszystkie wiersze z pliku między powiedzmy wierszami 16224 i 16482, a następnie przekierować je do nowego pliku?
unix
command-line
sed
text-processing
Adam J. Forster
źródło
źródło
Odpowiedzi:
Z podręcznika sed :
i
źródło
sed -n '16224,16482p;16483q' filename
. W przeciwnym razie sed będzie skanował do końca (a przynajmniej tak robi moja wersja).Gdzie 16224,16482 to numer linii początkowej i numer linii końcowej włącznie. Jest to indeks 1.
-n
tłumi echo wejścia jako wyjścia, czego wyraźnie nie chcesz; liczby wskazują zakres wierszy, na których działają następujące polecenia; poleceniep
wypisuje odpowiednie linie.źródło
sed -n '16224,16482p;16482q' orig-data-file > new-file
.Całkiem proste użycie głowy / ogona:
przy użyciu sed:
używając awk:
źródło
tail
.sed -n 16224,16482p' in.sql >out.sql
a polecenie awk powinno byćawk 'NR>=16224&&NR<=16482' in.sql > out.sql
head -16482 in.sql | tail -$((16482-16224)) >out.sql
obliczenia pozostawiają bashtail -n +16224
Możesz użyć „vi”, a następnie następującego polecenia:
Alternatywnie:
EDYCJA: - Aby dodać wyjaśnienie, użyj nagłówka -n 16482, aby wyświetlić pierwsze 16482 wiersze, a następnie użyj tail -n 258, aby uzyskać ostatnie 258 wierszy z pierwszego wyjścia.
źródło
cat
polecenia;head
może odczytać plik bezpośrednio. Jest to wolniejsze niż wiele alternatyw, ponieważ wykorzystuje 2 (3 jak pokazano) polecenia, w których 1 jest wystarczające.cat
). Inne rozwiązania wymagają co najmniej kilku minut. Wydaje się też, że najszybsza odmiana GNUtail -n +XXX filename | head XXX
.Istnieje inne podejście z
awk
:Jeśli plik jest ogromny, dobrze jest
exit
po przeczytaniu ostatniego żądanego wiersza. W ten sposób nie będzie niepotrzebnie czytać następujących wierszy:źródło
print; exit
. Dzięki !awk 'NR==16224, NR==16482; NR==16482 {exit}' file
źródło
źródło
powinien załatwić sprawę. Minusem tego podejścia jest to, że musisz wykonać arytmetykę, aby ustalić argument dla ogona i uwzględnić, czy chcesz, aby „między” obejmował linię końcową, czy nie.
źródło
cat
polecenia;head
może odczytać plik bezpośrednio. Jest to wolniejsze niż wiele alternatyw, ponieważ wykorzystuje 2 (3 jak pokazano) polecenia, w których 1 jest wystarczające.| tail -$((16482 - 16224))
.Stojąc na ramionach boxxar podoba mi się to:
na przykład
Te
$
środki „ostatnia linia”, więc pierwsza komenda powodujesed
wydrukować wszystkie linie zaczynające się na linii16224
i drugich marek dowodzeniased
rzucić po drukowaniu linii16428
. (Dodawanie1
opcjiq
-range w rozwiązaniu boxxar nie wydaje się konieczne).Podoba mi się ten wariant, ponieważ nie muszę dwukrotnie podawać numeru linii końcowej. Zmierzyłem, że używanie
$
nie ma szkodliwego wpływu na wydajność.źródło
sed -n '16224,16482p' < dump.sql
źródło
Szybko i brudno:
Prawdopodobnie nie jest to najlepszy sposób, ale powinien działać.
BTW: 259 = 16482-16224 + 1.
źródło
Napisałem program Haskell o nazwie splitter, który robi dokładnie to: przeczytaj mój post na blogu o wydaniu .
Możesz użyć programu w następujący sposób:
I to wszystko. Będziesz potrzebował Haskell, aby go zainstalować. Właśnie:
I gotowe. Mam nadzieję, że ten program okaże się przydatny.
źródło
splitter
tylko do odczytu ze standardowego wejścia? W pewnym sensie nie ma to znaczenia;cat
komenda jest zbędny czy to robi lub nie robi. Użyjsplitter 16224-16482 < somefile
albo (jeśli pobiera argumenty nazwy pliku)splitter 16224-16482 somefile
.Nawet my możemy to zrobić, aby sprawdzić w wierszu polecenia:
Na przykład:
źródło
cat
polecenia w żadnym z nich;sed
jest całkowicie zdolny do samodzielnego odczytu plików lub możesz przekierować standardowe wejście z pliku.Za pomocą ruby:
źródło
Już miałem opublikować trik z głową / ogonem, ale tak naprawdę prawdopodobnie po prostu odpalę emacsa. ;-)
otwórz nowy plik wyjściowy, zapisz ctl-y
Zobaczmy, co się dzieje.
źródło
Użyłbym:
FNR zawiera numer rekordu (linii) linii odczytywanej z pliku.
źródło
Chciałem zrobić to samo ze skryptu przy użyciu zmiennej i osiągnąłem to, umieszczając cudzysłowy wokół zmiennej $, aby oddzielić nazwę zmiennej od p:
Chciałem podzielić listę na osobne foldery, znalazłem wstępne pytanie i odpowiedziałem na użyteczny krok. (polecenie split nie jest opcją w starym systemie operacyjnym, do którego muszę przenieść kod).
źródło
Napisałem mały skrypt bash, który można uruchomić z wiersza poleceń, o ile aktualizujesz PATH tak, aby zawierał katalog (lub możesz umieścić go w katalogu, który jest już zawarty w PATH).
Zastosowanie: $ pinch nazwa pliku linia początkowa linia końcowa
źródło
wc
polecenia, które marnuje przepustowość dysku, szczególnie w przypadku plików gigabajtowych. Pod wieloma względami jest to dobrze udokumentowane, ale jest to również nadmiar umiejętności inżynieryjnych.To może Ci pomóc (GNU sed):
lub korzystając z bash:
źródło
Za pomocą ed:
-s
tłumi wyjście diagnostyczne; rzeczywiste polecenia znajdują się w ciągu tutaj. W szczególności16224,16482p
uruchamia poleceniep
(drukuj) w żądanym zakresie adresów linii.źródło
Opcja -n w zaakceptowanych odpowiedziach działa. Oto inny sposób na wypadek, gdybyś był skłonny.
Robi to:
źródło
cat file | sed
jest lepiej napisana jakosed file
Ponieważ mówimy o wydobywaniu wierszy tekstu z pliku tekstowego, dam specjalny przypadek, w którym chcesz wyodrębnić wszystkie wiersze pasujące do określonego wzorca.
Wydrukuje linię [Data] i pozostałe. Jeśli chcesz tekst od linii 1 do wzoru, wpisz: sed -n '1, / Data / p' mój_plik. Ponadto, jeśli znasz dwa wzorce (lepiej bądź unikalny w tekście), zarówno początkową, jak i końcową linię zakresu można określić za pomocą dopasowań.
źródło