Mam plik zawierający około 1000 wierszy. Chcę, aby część mojego pliku znajdowała się po wierszu, który pasuje do mojej instrukcji grep.
To jest:
$ cat file | grep 'TERMINATE' # It is found on line 534
Tak więc chcę plik z linii 535 do linii 1000 do dalszego przetwarzania.
Jak mogę to zrobić?
grep 'TERMINATE' file
grep
standardowego interfejsu wejściowego do wczytywania danych, zamiast konieczności uczenia się, do jakiego przełącznika zastosowaćgrep
, ised
, iawk
, ipandoc
,ffmpeg
itd., Kiedy chcemy czytać z pliku. Oszczędza to czas, ponieważ nie musimy uczyć się nowego przełącznika za każdym razem, gdy chcemy zrobić to samo: czytać z pliku.grep 'TERMINATE' < file
. Może to trochę utrudnia czytanie - ale to jest skrypt powłoki, więc to zawsze będzie problem :)Odpowiedzi:
Poniższe wypisze dopasowanie linii
TERMINATE
do końca pliku:Wyjaśnione:
-n
wyłącza domyślne zachowaniesed
drukowania każdej linii po wykonaniu na niej skryptu,-e
wskazany skryptsed
,/TERMINATE/,$
to wybór zakresu adresów (linii), co oznacza, że pierwsza linia pasuje doTERMINATE
wyrażenia regularnego (jak grep) do końca pliku ($
) , ip
jest poleceniem drukowania, które drukuje bieżący wiersz.Spowoduje to wydrukowanie z linii, która następuje po dopasowaniu linii
TERMINATE
do końca pliku:(od PO dopasowaniu linii do EOF, NIE włączając pasującej linii)
Wyjaśnione:
1,/TERMINATE/
to wybór zakresu adresów (linii), co oznacza pierwszą linię wejścia do pierwszej linii pasującej doTERMINATE
wyrażenia regularnego, id
jest to polecenie usuwania, które usuwa bieżącą linię i przeskakuje do następnej. Jakosed
domyślne zachowanie jest drukowanie linii, zostanie wydrukowana po linieTERMINATE
na końcu wejścia.Edytować:
Jeśli chcesz mieć wiersze przed
TERMINATE
:A jeśli chcesz, aby obie linie przed i po
TERMINATE
w 2 różnych plikach w jednym przebiegu:Pliki przed i po będą zawierały linię z zakończeniem, więc aby przetworzyć każdy, musisz użyć:
Edit2:
JEŚLI nie chcesz na stałe zakodować nazw plików w skrypcie sed, możesz:
Ale wtedy musisz pominąć
$
znaczenie ostatniej linii, aby powłoka nie spróbowała rozwinąć$w
zmiennej (zwróć uwagę, że teraz używamy podwójnych cudzysłowów wokół skryptu zamiast pojedynczych cudzysłowów).Zapomniałem powiedzieć, że nowa linia jest ważna po nazwach plików w skrypcie, aby sed wiedział, że nazwy plików się kończą.
Edycja: 2016-0530
Sébastien Clément zapytał: „Jak zamienić zakodowane na stałe
TERMINATE
zmienną?”Utworzyłbyś zmienną dla pasującego tekstu, a następnie zrobiłbyś to w taki sam sposób, jak w poprzednim przykładzie:
aby użyć zmiennej dla pasującego tekstu z poprzednich przykładów:
Ważne punkty dotyczące zastępowania tekstu zmiennymi w takich przypadkach to:
$variablename
) zawarte wsingle quotes
['
] nie "rozszerzają się", ale zmienne wewnątrzdouble quotes
["
] tak. Więc trzeba zmienić wszystkosingle quotes
, abydouble quotes
jeśli zawierają tekst, który chcesz zastąpić zmienną.sed
zakresy zawierają również$
i natychmiast następuje listem jak:$p
,$d
,$w
. Będą one również wyglądać zmiennych zostać rozszerzona, więc trzeba uciekać te$
znaki z backslashem [\
], takich jak:\$p
,\$d
,\$w
.źródło
sed -e "1,/$matchtext/d"
nie działa, gdy$matchtext
występuje w pierwszym wierszu. Musiałem to zmienić nased -e "0,/$matchtext/d"
.Jako proste przybliżenie, którego możesz użyć
który greps dla
TERMINATE
i wyprowadza do 100000 linii po tej linii.Ze strony podręcznika
źródło
file
zamiast tego policzyć wiersze :grep -A$(cat file | wc -l) TERMINATE file
Narzędziem do użycia jest awk:
Jak to działa:
Inne rozwiązania mogą zajmować dużo pamięci, jeśli używasz ich do bardzo dużych plików.
źródło
cat file | awk 'BEGIN{ found=0} /###/{found=found+1} {if (found<2) print }'
cat
.awk
jest doskonale w stanie przyjąć jedną lub więcej nazw plików jako argumenty. Zobacz także stackoverflow.com/questions/11710552/useless-use-of-catJeśli dobrze rozumiem pytanie prawidłowej chcą linie po
TERMINATE
, nie liczącTERMINATE
-line.awk
można to zrobić w prosty sposób:Wyjaśnienie:
if(found) print
) nie wypisze niczego, od czego można by zacząć.Będzie to wydrukować wszystkie linie po tym
TERMINATE
-line.Uogólnienie:
Przykład:
Wyjaśnienie:
found
jest ustawiony.found=1
tak, aby drukowane były następujące wiersze. Zauważ, że to sprawdzenie jest wykonywane po faktycznym wydrukowaniu, aby wykluczyć wiersz początkowy z wyniku.Uwagi:
BEGIN{found=0}
na początku wyrażenia awk.źródło
{if(found) print}
jest trochę anty-wzorzec w awk, bardziej idiomatyczne jest zastąpienie bloku tylkofound
lubfound;
później, jeśli będzie potrzebny inny filtr.awk '{if(found) print} /TERMINATE/{found=1}' your_file
zawk 'found; /TERMINATE/{found=1}' your_file
, należy oba robią to samo.Użyj rozwinięcia parametrów bash w następujący sposób:
źródło
printf
lub upewnić się, że wiesz dokładnie, do czego przekazujeszecho
.).grep -A 10000000 Plik 'TERMINATE'
źródło
Istnieje wiele sposobów, aby to zrobić z
sed
alboawk
:Szuka
TERMINATE
w Twoim pliku i drukuje od tego wiersza do końca pliku.To jest dokładnie to samo zachowanie co
sed
.W przypadku, gdy znasz numer linii, od której chcesz rozpocząć drukowanie, możesz podać go razem z
NR
(numer rekordu, który ostatecznie określa numer linii):Przykład
źródło
more +7 file
Jeśli z jakiegoś powodu chcesz uniknąć używania seda, poniższe wypisze pasującą linię
TERMINATE
do końca pliku:a następujący wiersz zostanie wydrukowany od następującego dopasowania wiersza
TERMINATE
do końca pliku:Potrzeba dwóch procesów, aby zrobić to, co sed może zrobić w jednym procesie, a jeśli plik zmieni się między wykonaniem grep i tail, wynik może być niespójny, więc zalecam użycie seda. Ponadto, jeśli plik nie zawiera
TERMINATE
, pierwsze polecenie kończy się niepowodzeniem.źródło
Alternatywy dla doskonałej
sed
odpowiedzi autorstwa jfgagne, które nie zawierają pasującego wiersza:awk '/TERMINATE/ {y=1;next} y'
( https://stackoverflow.com/a/18166628 )awk '/TERMINATE/ ? c++ : c'
( https://stackoverflow.com/a/23984891 )perl -ne 'print unless 1 .. /TERMINATE/'
( https://stackoverflow.com/a/18167194 )źródło
To może być jeden ze sposobów na zrobienie tego. Jeśli wiesz, w której linii pliku masz słowo grep i ile wierszy masz w swoim pliku:
grep -A466 Plik 'TERMINATE'
źródło
grep
nie jest nawet wymagany; możesz po prostu użyćtail -n $NUM
, więc to naprawdę nie jest odpowiedź.sed jest znacznie lepszym narzędziem do tego zadania: plik sed -n '/ re /, $ p'
gdzie re to regexp.
Inną opcją jest flaga grepa --after-context. Musisz przekazać liczbę na końcu, użycie wc na pliku powinno dać właściwą wartość zatrzymania. Połącz to z -n i swoim wyrażeniem dopasowującym.
źródło
Spowoduje to wyświetlenie wszystkich wierszy od ostatniej znalezionej linii „TERMINATE” do końca pliku:
źródło
grep
aby można go byłotail
podać, jest marnotrawnym antywzorem. Znalezienie dopasowania i wydrukowanie końca pliku (lub odwrotnie, wydrukowanie i zatrzymanie się na pierwszym dopasowaniu) jest wybitnie wykonywane za pomocą zwykłych, podstawowych narzędzi regex. Masywnośćgrep | tail | sed | awk
jest również sama w sobie masowym bezużytecznym wykorzystaniemgrep
przyjaciół i przyjaciół .tail
i wykonaj zadanie w bardziej wydajnym narzędziu. Zresztą tytuł wyraźnie mówi „pierwszy mecz”.