Jak wydrukować pierwszy wiersz za pomocą polecenia grep?

17

Mam plik o nazwie file.txt. Jak wydrukować pierwszy wiersz tylko za pomocą greppolecenia?

Nithin Santhosh
źródło
4
Czy head -1 file.txtnie działa?
clk
@steeldriver musisz odpowiedzieć, ponieważ jest to sposób na grep, dziwnie wybrane narzędzie do pracy.
MelBurslan,
1
grepnie jest najlepszym narzędziem do drukowania pierwszego wiersza pliku. Jeśli po prostu chciałeś wydrukować pierwszą pasującą linię greplub jeśli masz jakieś konkretne zastosowanie grep, daj nam znać, co to jest. Gdybyśmy mieli więcej kontekstu, być może moglibyśmy udzielić odpowiedzi, która lepiej pomogłaby Tobie i społeczności.
DKing,
@MelBurslan W pliku.txt Mam na przykład trzy linie: To jest nowy plik. Drugi wiersz: nazwa pliku to newFile. Trzeci wiersz: nie utworzyłem nowego wiersza. Więc używając polecenia grep, jak mogę wydrukować tylko pierwszy wiersz? Również w jaki sposób polecenie pomoże mi wydrukować zarówno pierwszą, jak i ostatnią linię? Czy możecie mi powiedzieć polecenia dla obu pytań?
Nithin Santhosh
Jeśli którakolwiek z istniejących odpowiedzi rozwiązuje problem, rozważ zaakceptowanie jej za pomocą znacznika wyboru. Dziękuję Ci!
Jeff Schaller

Odpowiedzi:

38

Chociaż jest to niekonwencjonalna aplikacja grep, możesz to zrobić za pomocą

grep -m1 "" file.txt

Działa, ponieważ puste wyrażenie pasuje do wszystkiego, a -m1powoduje , że grep kończy działanie po pierwszym dopasowaniu

-m NUM, --max-count=NUM
       Stop reading a file after NUM matching lines.
steeldriver
źródło
+1 za pokazanie, że banan w czekoladzie nie jest tak bezużyteczny, jak myślałem.
Kamil Maciorowski
4
To może działać na niektórych systemach, ale nie jest przenośne:grep: unknown option -- m
Kusalananda
1
Zwróć uwagę na różnicę między „pierwszą linią” a „pierwszą linią dopasowaną”
Charles
13

To nie jest coś grep. Sama nazwa „grep” jest akronimem „ globalnie wyszukaj wyrażenie regularne i drukuj”, czyli to, co robi edpolecenie g/re/p(dla danego wyrażenia regularnego re).

edto interaktywny edytor linii z 1969 roku, ale najprawdopodobniej jest dzisiaj zainstalowany w twoim systemie. Otrzymaliśmy grepod ed, i może to być postrzegane jako skrót lub alias dla określonej funkcjonalności edi sed, i który jest „stream- ed”, tj. ( Nieinteraktywny ) edytor strumienia.

Użyjmy sedzamiast tego:

$ sed -n '1p' file.txt

1pCiąg jest malutki sed„skrypt”, która drukuje ( p) linia odpowiadająca danym adresem ( 1pierwsza linia). Nawiasem mówiąc , polecenie edycji 1p( ednawiasem mówiąc ) zrobiłoby to samo w edytorze.

-nHamuje wyjście z niczym nie wyraźnie wydrukowanym przez skrypt, więc wszyscy mamy to pierwsza linia pliku file.txt.

Alternatywnie:

$ sed '1q' file.txt

Spowoduje to wydrukowanie wszystkich linii pliku, ale zamyka ( q) w linii 1 (po wydrukowaniu). Jest to dokładnie równoważne z head -n 1 file.txt.

W standardzie POSIX jest napisane (uogólniające), że head -n Njest to tak samo jak sed 'Nq'np. „Wypisz każdą linię, ale wyjdź za linię N”. Powód headzostał uwzględniony w standardzie w ogóle z powodu symetrii z tail(i wstecznej kompatybilności z istniejącymi implementacjami Unixa).

Kusalananda
źródło
To najbardziej pouczająca odpowiedź, pierwsza odpowiedź to dziwny hack. Wiedziałem, że jest coś dziwnego, dziękuję za pokazanie mi historii grep i ed. Teraz wszystko nabiera sensu.
Tomas Zubiri,
6

O ile pierwszy wiersz nie zawiera unikatowego ciągu, nie można tego zrobić przy użyciu tylko grep. head -n 1 file.txtdziałałby na swoim miejscu.

Jeśli chcesz wydrukować tylko pierwszy wiersz, jeśli pasuje on do wzorca, podłącz rurkę do grep

head -n 1 * | grep [pattern]

Kurt Heisel
źródło
2

Jeszcze inne niekonwencjonalne użycie Grep - transformacja Schwartziana, która przechodzi przez kilka cyrkulacji, aby numerować linie, następnie używa grep do szukania numeru linii, a następnie z powrotem usuwa numer linii:

function grep1() (
  nlines=$(wc -l < "$1")
  nlw=$(printf "%d" "$nlines" | wc -c)
  nl -d '\n' -ba -n ln -w "$nlw" -s ' ' "$1" | grep '^1 ' | sed 's/^1 *//'
)

function greplast() (
  nlines=$(wc -l < "$1")
  nlines=$((nlines + 0))
  nlw=$(printf "%d" "$nlines" | wc -c)
  nl -d '\n' -ba -n ln -w "$nlw" -s ' ' "$1" | grep "^$nlines " | sed "s/^$nlines *//"
)

Kładę tę odpowiedź tutaj jako przykład pomysł, że tylko dlatego, że można coś zrobić (lub bash grep lub ... itd), nie oznacza, że powinna - nie ma chyba lepszego narzędzia do pracy. sed ( sed 1qlub sed -n 1p) i head ( head -n 1) to bardziej odpowiednie narzędzia do drukowania pierwszego wiersza z pliku. Do drukowania ostatniego wiersza pliku masz tail -n 1lubsed -n '$p'. Narzędzia te są nie tylko jednym poleceniem (zamiast 3+ w powyższych funkcjach), ale są również znacznie czytelniejsze dla przyszłych czytelników - być może dla ciebie! - ze skryptów, w których się znajdują. Chociaż nie jestem jednym z (obecnie 3) głosujących w dół twojego pytania, jest prawdopodobne, że twój nacisk na arbitralne narzędzie do pracy (bez żadnych uzasadnień) jest powodem opinie negatywne. Jest bardzo mało prawdopodobne, że system, który ma grepnie mieć head, taili sed.

Jeff Schaller
źródło