Wyobraź sobie wynik polecenia takiego jak
44444
55555
11111
22222
33333
jak mogę wyciągnąć pierwsze N wierszy (pierwsze dwa w powyższym przykładzie) i dołączyć je na końcu, ale bez użycia pliku tymczasowego (a więc tylko przy użyciu potoków)?
11111
22222
33333
44444
55555
Coś w stylu | sed -n '3,5p;1,2p'
(co oczywiście nie działa, ponieważ sed nie dba o kolejność poleceń).
command-line
text-processing
Peter Uhnak
źródło
źródło
Odpowiedzi:
Po prostu skopiuj te linie do bufora wstrzymania (a następnie je usuń), a gdy w ostatnim wierszu dołącz zawartość bufora wstrzymania do przestrzeni wzorów:
Ze
gnu sed
można napisać go jakoOto inny sposób z ol '
ed
(r
wprowadza wyjściesome command
do bufora tekstowego, a następniem
usuwa wiersze1,NUMBER
po$
pierwszym):Zauważ, że - jak wskazano - oba się nie powiedzie, jeśli wyjście ma mniej niż
NUMBER
+1 linii. Bardziej solidnym podejściem byłoby (gnu sed
składnia):ten usuwa tylko wiersze z tego zakresu, o ile nie są one ostatnim wierszem (
$!d
) - w przeciwnym razie nadpisuje przestrzeń wzorca zawartością bufora wstrzymania (g
), a następnieq
usuwa (po wydrukowaniu bieżącej przestrzeni wzorca).źródło
sed -e '1,NUMBER{H;1h;d;}' -e '$G'
działa również przenośnie (zwróć uwagę, że niektóresed
implementacje nie mogą pomieścić więcej niż kilka kilobajtów w przestrzenised -e '1,NUMBER{H;1h;d' -e'}' -e '$G'
?-e
zastępuje nowy wiersz.d;}
nie jest jeszcze POSIX, ale przenośny. Zostanie to naprawione w następnej specyfikacji POSIX. Zobacz austingroupbugs.net/view.php?id=944#c27201,NUMBER{H;1h;d;}
to brak średnika bezpośrednio po nawiasie otwierającym . To mógł być tylko błąd w SunOS 4.1,sed
którego obejście jest nadal w moich palcach 20 lat później.awk
Podejście:Jedną z korzyści w stosunku do
sed
podejścia @ don_crissti jest to, że nadal działa (wysyła wiersze), jeśli wyjście man
wiersze lub mniej.źródło
\n
ORS, aby działało to z innymi separatorami rekordów (powiedz, że chcesz używać akapitów itp.).Mam
xclip
i dzięki temu można to zrobić w następujący sposób:Oto jego opis:
źródło
Sposób Perla:
Lub to samo napisane mniej tajemniczo:
Na przykład:
Wyjaśnienie
-ne
: przeczytaj plik wejściowy / strumień wiersz po wierszu i zastosuj skrypt podany przez-e
dla każdego wiersza.$.<3
:$.
to bieżący numer linii, więc zmień3
na liczbę linii, które chcesz przesunąć.$.<3?($f.=$_):print;
: to jest operator warunkowy, ogólny format brzmi:condition ? case1 : case2
będzie działał,case1
jeślicondition
jest prawdziwy, acase2
jeśli jest fałszywy. Tutaj, jeśli bieżący numer linii jest mniejszy niż 3, dołącza bieżącą linię ($_
) do zmiennej$f
i, jeśli numer linii jest większy niż 3, drukuje.}{ print $f
:}{
jest to skrót perlaEND{}
. Będzie działał po przetworzeniu wszystkich linii wejściowych. W tym momencie zbierzemy wszystkie linie, które chcemy przesunąć i wydrukujemy wszystkie, które chcemy zostawić w spokoju, więc wydrukuj linie zapisane jako$f
.źródło
perl -ne '$.<3?$f.=$_:print}{print $f
Użyj POSIX
ex
. Tak, jest przeznaczony do edycji plików, ale będzie działał w potoku.Może to mieć dowolne dowolne polecenia dodane na początku lub na końcu potoku i będzie działać tak samo. Jeszcze lepiej, biorąc pod uwagę obecność
/dev/stdin
, jest zgodny z POSIX.(Nie wiem, czy
/dev/stdin
jest określony w POSIX, czy nie, ale widzę, że jest obecny zarówno w systemie Linux, jak i Mac OS X.)Ma to przewagę w zakresie czytelności w porównaniu do korzystania
sed
z miejsca trzymania - po prostu mówiszex
„przenieś te linie do końca” i tak się dzieje. (Reszta poleceń oznacza „wydrukuj bufor” i „exit”, które również są dość czytelne.)NB:
ex
Polecenie podane powyżej zakończy się niepowodzeniem, jeśli jako dane wejściowe podano mniej niż 2 linie.Dalsza lektura:
źródło
Krótki
python
fragment:Przekaż nazwę pliku jako pierwszy argument i liczbę wierszy do przeniesienia jako drugi argument.
Przykład:
źródło
Jeśli możesz zapisać całe wyjście w pamięci:
źródło
Oto kolejna opcja, która wymaga GNU
sed
:-u
sprawia, że GNU nie jestsed
buforowane, tak żesed
polecenie nie zużywa więcej niż 3 wiersze STDIN. Podstawienie polecenia usuwa puste linie, dzięki czemu polecenie nie zawiera pustych linii na końcu danych wyjściowych, jeśli trzeci, trzeci i drugi lub trzeci, drugi i pierwszy wiersz są puste.Możesz także zrobić coś takiego:
Bez
sponge /dev/stdout|
polecenia zawiodłoby przy długich wejściach.sponge /dev/stdout
może być również zastąpione przeztac|tac
, nawet jeśli drukuje to na przykład,a\ncb
jeśli wejście jesta\nb\nc
tam, gdzie\n
jest linia, lub(x=$(cat);printf %s\\n "$x")
, nawet jeśli usuwa puste linie z końca wejścia. Powyższe polecenie usuwa pierwszy wiersz, gdy liczba wierszy wejścia wynosi jeden lub dwa.źródło