Jak usunąć wszystkie wiersze w pliku, zaczynając od pasującego wiersza?

84

Mam plik, który składa się z kilku wierszy tekstu:

The first line
The second line
The third line
The fourth line

Mam ciąg, który jest jedną z linii: The second line

Chcę usunąć ciąg i wszystkie wiersze po nim w pliku, więc usunie The third linei The fourth lineoprócz ciągu. Plik stałby się:

The first line

Szukałem rozwiązania w google i wydaje mi się, że powinienem skorzystać sed. Coś jak:

sed 'linenum,$d' file

Ale jak znaleźć numer wiersza łańcucha? Albo jak inaczej mam to zrobić?

DocWiki
źródło
Twoje stwierdzenie problemu jest sprzeczne: „Chcę usunąć wszystkie wiersze po wierszu” oznacza, że ​​usuwasz tylko dwa wiersze (tak jak mówisz), ale w Twoim przykładzie wynikowym również brakuje linii dopasowania. Czego tak naprawdę chcesz?
Jonathan Leffler
Pasująca linia ORAZ wszystkie wiersze po niej. Powinienem poprawić swój angielski. Dziękuję za informację.
DocWiki
powiązany stackoverflow.com/questions/17364951/…
Trevor Boyd Smith

Odpowiedzi:

136

Jeśli nie chcesz drukować dopasowanej linii (lub dowolnych następujących):

sed -n '/The second line/q;p' inputfile

To mówi "kiedy dojdziesz do linii, która pasuje do wzorca zakończ, w przeciwnym razie wypisz każdą linię". Ta -nopcja zapobiega niejawnemu drukowaniu, a ppolecenie jest wymagane do jawnego drukowania wierszy.

lub

sed '/The second line/,$d' inputfile

To mówi „usuń wszystkie wiersze z wyjścia, zaczynając od dopasowanej linii i kontynuując do końca pliku”.

ale pierwszy jest szybszy. Jednak zakończy przetwarzanie całkowicie, więc jeśli masz wiele plików jako argumenty, te po pierwszym pasującym pliku nie zostaną przetworzone. W takim przypadku formularz usuwania jest lepszy.

Jeśli chcesz wydrukować dopasowaną linię, ale nie wszystkie następujące wiersze:

sed '/The second line/q' inputfile

To mówi "wypisz wszystkie linie i zakończ, gdy dopasowana linia zostanie osiągnięta" ( -nopcja (brak niejawnego drukowania) nie jest używana).

Dodatkowe informacje można znaleźć w man sed .

Wstrzymano do odwołania.
źródło
3
Ale niektóre polecenia denerwują się z powodu pękniętych rur ( co -pna przykład RCS ), a wtedy lepiej jest z sed '/The second line/,$d'notacją.
Jonathan Leffler
Czy możesz dodać wyjaśnienia?
Ahmad Abdelghany
@AhmadAbdelghany: Dodano wyjaśnienia.
Wstrzymano do odwołania.
@DennisWilliamson Wielkie dzięki.
Ahmad Abdelghany
pierwsza metoda dwukrotnie drukuje ostatnią linię przed dopasowaną linią. usuwanie ppo ;pracach.
CrazyFrog,
27

To trochę krócej niż inne podane rozwiązania. Zakończ, używając dużego Q, aby uniknąć drukowania bieżącej linii.

 sed '/The second line/Q' file

Aby faktycznie usunąć wiersze, możesz użyć tej samej składni.

 sed -i '/The second line/Q' file
jaap
źródło
1
To zdecydowanie moje ulubione rozwiązanie.
TryTryAgain
5
sed '/The second line/q0' file

Lub bez gnu sed:

sed '/The second line/q' file

Lub używając grep:

grep -B 9999999 "The second line"
Erik
źródło
Wielkie dzięki! Czy możesz mi powiedzieć, jak mogę znaleźć numer wiersza określonego ciągu, którego nadal nie znam.
DocWiki
grep -n Plik "Druga linia" | awk -F: '{print $ 1}'
Erik
@DocWiki: nie potrzebujesz numeru linii; szukasz tego. sed "/$string/,\$d" inputfile.
Jonathan Leffler
5

Korzystanie z awk (bez pokazywania dopasowanej linii)

awk '/pattern/ {exit} {print}' file.txt
Joel Arnold
źródło
To najlepsza odpowiedź, ponieważ możesz nie znać wartości drugiej linii.
RonJohn
0

Najpierw dodaj numer linii i usuń linię

cat new.txt 
The first line
The second line
The third line
The fourth line

 cat new.txt  | nl
     1  The first line
     2  The second line
     3  The third line
     4  The fourth line



cat new.txt  | nl | sed  "/2/d"
     1  The first line
     3  The third line
     4  The fourth line

cat new.txt  |  nl |sed  "3d;4d"
     1  The first line
     2  The second line

używając awk

awk 'NR!=3 && NR!=4' new.txt 
The first line
The second line
sush
źródło
0
awk '/The second line/{exit}1' file
kurumi
źródło