Hallo, On Fri, 17 Jan 2003, Bernd Brodesser wrote:
* David Haller schrieb am 17.Jan.2003:
$ rpm -qa \ --queryformat="%{installtime} %{installtime:date} \t%{name}-%{version}\n" \ | sort -n | cut -d' ' -f2- | sed -n '1{p;n;p;};${x;p;x;p;};h'
Ich habe verstanden, was Du da machst. ;)
Schick, gell? ;)
Aber das ist ja wohl etwas mehr als nur Tricky. Außerdem habe ich festgestellt, daß die deutsche Manpage wieder mal ein wenig daneben ist.
================================================================= n der Inhalt des Arbeitsspeichers wird unverändert in die Ausgabe geschrieben und der Arbeitsspeicher durch die nächste Eingabezeile ersetzt =================================================================
Jep. Mit "ausgeben" hat n genau garnix zu tun nur mit dem lesen. ==== n N Read/append the next line of input into the pattern space. ==== Da sed (ohne -n) als letztes immer den pattern space ausgibt ist dann auch die Folge klar, mit -n dann auch (je nach dem ob ein p folgt oder nicht).
Das stimmt bei de Option -n ja wohl nicht so ganz. ;) Hat mich zumindest verwirrt. Das 1{p;n;p;} ist somit klar, es werden die ersten beiden Zeilen ausgegeben. Mit ${x;p;x;p};h werden die letzten beiden Zeilen ausgegeben. Aber das funktioniert nur, weil mit dem h jede Zeile in den Puffer geschrieben wird.
Genau.
Bei der letzten Zeile wird denn zuerst der Puffer, und dann der Arbeitsspeicher ausgegeben. Genauer: Arbeitsspeicher und Puffer vertauscht, Der ehemalige Puffer, der jetzt im Arbeitsspeicher steht ausgegeben, wieder zurückgetauscht und dann wieder der Arbeitsspeicher ausgegeben. Und wegen dem h steht im Puffer die vorletzte Zeile.
Exakt :) Grad find ich noch ne einfachere Variante (ich hab's nach dem cut in ne Datei umgeleitet): sed -n '1{p;n;p;};${x;G;p;};h' < /tmp/rpmlist Hier haben wir die vorletzte Zeile im hold-space, dann vertauschen wir (wg. der Reihenfolge), haengen die letzte Zeile (die nun im hold-space ist) an die vorletzte im pattern-space an und geben beide aus ;)
Soweit so gut. Aber doch wohl ein wenig sehr Tricky, und vor allem, wenn man die drei ersten Zeilen ausgeben will, kein Problem, aber bei den drei letzten wird es haarig.
Jup.
Kann es sein, daß bei Linux ein *einfacher* Filter fehlt, mit dem man bestimmte Zeilen ausgeben kann?
Ja. Aber s.u. :)
Also etwa die ersten drei Zeilen und die letzten drei,
$ sed -n '1{N;N;p;};${x;G;p;};N;h;' /tmp/rpmlist Mon 16 Aug 1999 07:19:26 PM CEST bc-1.04 Mon 16 Aug 1999 07:19:30 PM CEST tcsh-6.08.05 Mon 16 Aug 1999 08:27:13 PM CEST aaa_dir-99.7.12 Fri 29 Nov 2002 12:30:18 PM CET util-linux-2.11u Fri 06 Dec 2002 12:47:46 PM CET MPlayer-0.90pre6 Thu 12 Dec 2002 01:09:28 AM CET kbd-1.06 *Uffa* ;) Aber 4-zeilig bekomm ich's nimmer hin. Das naheliegende sed -n '1{N;N;N;p;};${x;G;p;};N;N;h;' /tmp/rpmlist funktioniert nicht. Aber eigentlich kann man ja sowas per 'head -N datei; tail -N datei' machen... ,----[ ~/bin/headntail ] | #!/bin/sh | exec 3>/dev/stdout | test -n "$IN" && unset IN | case "$#" in | 0) N="-10"; IN="/dev/stdin";; | 1) case "$1" in | -*) N="$1"; IN="/dev/stdin";; | *) N="-10";; | esac;; | *) case "$1" in | -*) N="$1"; shift;; | *) N="-10";; | esac;; | esac | test -n "$IN" && set -- "$IN" | for f in "$@"; do | ( cat "$f" | tee /dev/stderr | head $N 1>&3 ) 2>&1 | tail $N | done `---- $ cat /tmp/rpmlist | headntail -1 Mon 16 Aug 1999 07:19:26 PM CEST bc-1.04 Thu 12 Dec 2002 01:09:28 AM CET kbd-1.06
oder nur jede zweite Zeile usw.?
sed -n '1~2p' steht sogar als Beispiel in man -L en sed ;)
Klar kann man das mit awk oder perl machen. Aber zumindest mit perl kann man auch grep vollständig ersetzen, trotzdem hat grep seine Berechtigung.
ACK. -dnh -- Breathing in a full grown eucalyptus tree is something worth watching. Attaching inhalers to eucalyptus trees achieves little and annoys the trees. -- Geoff Lane in the SDM