Czy jest jakieś polecenie bash, które pozwoli ci uzyskać n-ty wiersz STDOUT?
To znaczy, coś, co by to wzięło
$ ls -l
-rw-r--r--@ 1 root wheel my.txt
-rw-r--r--@ 1 root wheel files.txt
-rw-r--r--@ 1 root wheel here.txt
i zrób coś takiego
$ ls -l | magic-command 2
-rw-r--r--@ 1 root wheel files.txt
Zdaję sobie sprawę, że byłoby to złą praktyką podczas pisania skryptów przeznaczonych do ponownego użycia, ALE podczas codziennej pracy z powłoką przydałaby mi się możliwość filtrowania mojego STDOUT w taki sposób.
Zdaję sobie również sprawę, że byłoby to trywialne polecenie do napisania (buforuj STDOUT, zwróć konkretną linię), ale chcę wiedzieć, czy istnieje jakieś standardowe polecenie powłoki, które by to zrobiło, które nie byłoby dostępne bez umieszczania skryptu na swoim miejscu.
magic-command
Odpowiedzi:
Używanie
sed
tylko dla odmiany:Użycie tej alternatywy, która wygląda bardziej wydajnie, ponieważ przestaje czytać dane wejściowe po wydrukowaniu wymaganego wiersza, może wygenerować SIGPIPE w procesie podawania, co z kolei może wygenerować niepożądany komunikat o błędzie:
Widziałem to tak często, że zwykle używam pierwszego (co i tak jest łatwiejsze do pisania), chociaż
ls
nie jest to polecenie, które narzeka, gdy otrzymuje SIGPIPE.Dla szeregu linii:
Dla kilku zakresów linii:
źródło
p
tosed
instrukcja, która drukuje linie identyfikowane przez zakres linii, które ją poprzedzają. Oznacza2,4p
to, że drukuje linie 2, 3, 4.n
oznacza NIE drukowanie wszystkich pozostałych wierszyźródło
head -n 2 | tail -n 1
- nowoczesne głowy i ogony zwykle wydają ostrzeżenia w przeciwnym razie.head -n M | tail -n M-N+1
), a generalizacja do obsługi wielu zakresów nie jest możliwa.$ ls -l | awk '{if (NR>=4 && NR<=64) print}'
(można łatwiej dodać więcej warunków, wiele zakresów itp.)Alternatywa dla ładnego sposobu głowa / ogon:
lub
źródło
'2p'
oznacza?2
jest zmienną? Każdy przykład używa pojedynczych cudzysłowów, ale w przypadku zmiennej var potrzebujesz podwójnych cudzysłowów. Czy możemy „zaprogramować” awk do pracy również z pojedynczymi cudzysłowami podczas korzystania z vars? Przykładline =1; ls | awk 'NR==$line'
. Wiem, żebash
używa podwójnych cudzysłowów z zmiennymi.Od sed1line :
Z awk1line :
źródło
Dla kompletności ;-)
krótszy kod
krótsze życie
źródło
ls
- oryginalne pytanie dotyczyło czyjegoś pytaniaSTDOUT
, więc pomyślałem, że lepiej jest je powiększyć.{ print $0 }
, więc `awk 'NR == 3' jest krótszym sposobem na napisanie tego samego.Wypróbuj tę
sed
wersję:Mówi „usuń wszystkie wiersze, które nie są drugim”.
źródło
Możesz użyć awk:
Aktualizacja
Powyższy kod nie otrzyma tego, czego chcemy z powodu błędu off-by-one: pierwszy wiersz polecenia ls -l jest wierszem całkowitym . W tym celu zadziała następujący poprawiony kod:
źródło
Czy Perl jest łatwo dostępny?
Oczywiście zamień 7 na dowolną liczbę.
źródło
$ awk 'NR % 7' filename
aby wydrukować co 7 linię w pliku.Sugerowany inny plakat
ale jeśli włożysz głowę w ogon, wygląda na to, że wszystko do linii N jest przetwarzane dwukrotnie.
Wbijając ogon w głowę
byłby bardziej wydajny?
źródło
Tak, najbardziej wydajnym sposobem (jak już wskazał Jonathan Leffler) jest użycie sed z print & quit:
źródło
Hmm
sed nie działał w moim przypadku. Proponuję:
źródło
Więcej kompletności ..
Wyrzucaj linie, aż dojdziesz do drugiej, a następnie wydrukuj pierwszą linię. Tak więc drukuje trzecią linię.
Jeśli to tylko druga linia ...
Umieść tyle lektur, ile potrzeba.
źródło
Dodałem to do mojego .bash_profile
I to działa
źródło