Discussion:
ignore 43988.10
(zu alt für eine Antwort)
Marcel Logen
2021-02-21 19:55:32 UTC
Permalink
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen. Daher jetzt ein wenig umständlich
[...]

Gibt es da vielleicht eine andere/einfachere
Oneliner-Lösung (ohne externe Datei)?

Ich hatte auch an "awk" gedacht, bin damit aber
auch nicht weitergekommen.

Interessiert,
Marcel

Fup2 de.comp.os.unix.shell
--
╭────────╮ ╭──╮ ╭─╮ ╭────────────────╮
╰────╮ ╰─╯ ╰────╯ │ ╰───────────╮ ╭─╯ ╭
╭───╮ ╰─╮ ╭──────────╯ ╭─╮ ╭─────╮ ╭──╮ ╭─╯ │ ╭──╮ ╭─╯
─╯ ╰────╯ ╰─────────────╯ ╰────╯ ╰─╯ ╰─╯ ╰─────────╯ ╰───╯
Marcel Logen
2021-02-21 19:59:09 UTC
Permalink
Post by Marcel Logen
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen. Daher jetzt ein wenig umständlich
[...]
Gibt es da vielleicht eine andere/einfachere
Oneliner-Lösung (ohne externe Datei)?
Ich hatte auch an "awk" gedacht, bin damit aber
auch nicht weitergekommen.
Interessiert,
Marcel
Fup2 de.comp.os.unix.shell
[Subject angepaßt]
--
╭────────────────╮ ╭──╮
─╮ ╰─────────╮ ╭─╯ ╭─╯ ╰─╮ ╭─╮ ╭─╮
╰─╮ ╭─╮ ╭────╮ ╭─╯ ╰──╮ │ ╭───╯ ╭─────╯ ╰─╮ ╭─╮ ╭─╯ ╰─────╮
╰───╯ ╰──╯ ╰──╯ ╰─╯ ╰───────╯ ╰─╯ ╰──╯ ╰─
Stefan Wiens
2021-02-22 08:27:28 UTC
Permalink
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen. Daher jetzt ein wenig umständlich
[...]
Ein schneller Hack:

$ seq 1 20 | sed -n '
1,5p
6,${
H
x
s/^.*\n\(\([^\n]*\n\)\{4\}[^\n]*\)$/\1/
x
}
${
x
p
}
'
1
2
3
4
5
16
17
18
19
20

Das kann man sicher noch schöner formulieren.
--
Stefan
Stefan Wiens
2021-02-22 08:34:08 UTC
Permalink
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen. Daher jetzt ein wenig umständlich
[...]
Ein schneller Hack:

$ seq 1 20 | sed -n '
1,5p
6,${
H
x
s/^.*\n\(\([^\n]*\n\)\{4\}[^\n]*\)$/\1/
x
}
${
x
p
}
'
1
2
3
4
5
16
17
18
19
20

Das kann man sicher noch schöner formulieren. Irgendwie ist ein Newline
zu viel im Pattern space.
--
Stefan
Stefan Wiens
2021-02-22 08:34:53 UTC
Permalink
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen. Daher jetzt ein wenig umständlich
[...]
Ein schneller Hack:

$ seq 1 20 | sed -n '
1,5p
6,${
H
x
s/^.*\n\(\([^\n]*\n\)\{4\}[^\n]*\)$/\1/
x
}
${
x
p
}
'
1
2
3
4
5
16
17
18
19
20

Das kann man sicher noch schöner formulieren. Irgendwie ist ein Newline
zu viel im Hold space.
--
Stefan
Axel Reichert
2021-02-22 09:30:57 UTC
Permalink
Marcel Logen <333200007110-***@ybtra.de> writes:

[siehe Subject-Zeile]

Als Schnellschuss:

(head -n 13 foo.txt; tail -n 13 foo.txt) | uniq

Tschoe!

Axel
Stefan Wiens
2021-02-22 10:17:08 UTC
Permalink
Script verbessert.
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen.[...]
Nächster Anlauf mit sed:

sed -n '
1,3p
3,${
3b
H
x
s/^\n[^\n]*\(\(\n[^\n]*\)\{3\}$\)/\1/
x
}
${
x
s/^\n//p
}
'


Das überschüssige "\n" entsteht beim ersten "H" auf den leeren
Hold space. Das Entfernen bei der Ausgabe testet also auch,
ob "H" überhaupt ausgeführt wurde. Das "b"-Kommando hat den Zweck,
dass man überall "3" schreiben kann anstatt rumzurechnen.

Diese Version sollte auch mit Leerzeilen klarkommen.
--
Stefan
Marcel Logen
2021-03-01 15:50:33 UTC
Permalink
Post by Stefan Wiens
sed -n '
1,3p
3,${
3b
H
x
s/^\n[^\n]*\(\(\n[^\n]*\)\{3\}$\)/\1/
x
}
${
x
s/^\n//p
}
'
Das überschüssige "\n" entsteht beim ersten "H" auf den leeren
Hold space. Das Entfernen bei der Ausgabe testet also auch,
ob "H" überhaupt ausgeführt wurde.
Danke, soweit klar. Ich habe mich jetzt mal ein wenig
mit "H", "x" und "p" vertraut gemacht. Mit "H" kann man
dann wohl, wenn ich das richtig sehe, eine ganze Datei
per sed einlesen.

Eine andere (selbstgestellte) Aufgabe ist das Er-
setzen von "=\n\n" durch "\n" (newline) in einem
Datenstrom oder einer Datei, was nach meinen Erkennt-
nissen mit sed oder awk - da diese ja normalerweise
AFAICS zeilenorientiert arbeiten - nicht so ganz ein-
fach möglich ist.

Ich habe es mit sed aber nun wie folgt hinbekommen:

| ***@o15:~/ybtra-o15/sed-awk-streamtest$ cat -vET input2
| Anfang=$
| etwas=$
| noch etwas=$
| $
| weiter=$
| Fortsetzung=$
| hallo=$
| $
| und wieder weiter=$
| zwei=$
| drei=$
| $
| $
| unten=$
| ENDE$
| ***@o15:~/ybtra-o15/sed-awk-streamtest$ sed -n -e '{H;x;s/=\n\n/\n/;x};${x;s/^\n//;p}' input2 | cat -vET
| Anfang=$
| etwas=$
| noch etwas$
| weiter=$
| Fortsetzung=$
| hallo$
| und wieder weiter=$
| zwei=$
| drei$
| $
| unten=$
| ENDE$
| ***@o15:~/ybtra-o15/sed-awk-streamtest$

Mit awk geht es z. B. so:

| ***@o15:~/ybtra-o15/sed-awk-streamtest$ awk 'BEGIN{RS="=\n\n"}{print}' input2 | cat -vET
| Anfang=$
| etwas=$
| noch etwas$
| weiter=$
| Fortsetzung=$
| hallo$
| und wieder weiter=$
| zwei=$
| drei$
| $
| unten=$
| ENDE$
| $
| ***@o15:~/ybtra-o15/sed-awk-streamtest$

Da entsteht am Ende ein newline, was aber nicht weiter
schlimm ist.
Post by Stefan Wiens
Das "b"-Kommando hat den Zweck,
dass man überall "3" schreiben kann anstatt rumzurechnen.
Das habe ich leider noch nicht verstanden.
Post by Stefan Wiens
Diese Version sollte auch mit Leerzeilen klarkommen.
Ja - soweit ich das sehe.

Marcel
--
╭────────╮ ╭───╮ ╭─────╮
╰──────╮ │ │ ╰─╮ ╰─╮ │ ╭──╮
╭─╮ ╭─╮ ╭──╮ ╭─╯ ╰───╯ ╭─╯ ╭─╯ ╰─╮ ╭──╯ ╰──
──────────────╯ ╰─╯ ╰─╯ ╰─╯ ╰────╯ ╰──────────╯
Stefan Wiens
2021-03-01 22:08:29 UTC
Permalink
Post by Marcel Logen
Post by Stefan Wiens
sed -n '
1,3p
3,${
3b
H
x
s/^\n[^\n]*\(\(\n[^\n]*\)\{3\}$\)/\1/
x
}
${
x
s/^\n//p
}
'
Das überschüssige "\n" entsteht beim ersten "H" auf den leeren
Hold space. Das Entfernen bei der Ausgabe testet also auch,
ob "H" überhaupt ausgeführt wurde.
Danke, soweit klar. Ich habe mich jetzt mal ein wenig
mit "H", "x" und "p" vertraut gemacht. Mit "H" kann man
dann wohl, wenn ich das richtig sehe, eine ganze Datei
per sed einlesen.
Das ginge auch mit "N" (man braucht Begrenzungszeichen, die nicht in
der Eingabe vorkommen). Siehe z. B. dc.sed.

Aber eine ganze Datei einzulesen ist nicht das Konzept von sed(1).

Denn sed ist ein Stream editor.

Der sollte also mit beliebig großen Eingaben zurechtkommen (auch größer
als sämtlicher verfügbarer Speicher auf dem System).

Man sollte also alle Daten, die nicht mehr für eine weitere Verarbeitung
relevant sind, wegwerfen, und ansonsten auf die Speicherverwaltung von
sed vertrauen.
Post by Marcel Logen
Eine andere (selbstgestellte) Aufgabe [...]
Das schaue ich mir bei Gelegenheit an.
Post by Marcel Logen
Post by Stefan Wiens
Das "b"-Kommando hat den Zweck,
dass man überall "3" schreiben kann anstatt rumzurechnen.
Das habe ich leider noch nicht verstanden.
Alle Ziffern "3" beziehen sich auf die Fragestellung (ich habe "13" auf
"3" reduziert). Sonst müsste man halt "4${" schreiben und die Shell oder
wer auch immer müsste es ausrechnen. "b3" springt zum Ende des Scripts,
denn bis dahin sin noch keine auszugebenden Daten gesammelt worden.
--
Stefan
Marcel Logen
2021-03-03 16:08:06 UTC
Permalink
Post by Stefan Wiens
Post by Marcel Logen
Post by Stefan Wiens
sed -n '
1,3p
3,${
3b
H
x
s/^\n[^\n]*\(\(\n[^\n]*\)\{3\}$\)/\1/
x
}
${
x
s/^\n//p
}
'
[...]
Post by Stefan Wiens
Post by Marcel Logen
Danke, soweit klar. Ich habe mich jetzt mal ein wenig
mit "H", "x" und "p" vertraut gemacht. Mit "H" kann man
dann wohl, wenn ich das richtig sehe, eine ganze Datei
per sed einlesen.
Das ginge auch mit "N" (man braucht Begrenzungszeichen, die nicht in
der Eingabe vorkommen). Siehe z. B. dc.sed.
<http://sed.sourceforge.net/grabbag/scripts/dc.sed>?
Post by Stefan Wiens
Aber eine ganze Datei einzulesen ist nicht das Konzept von sed(1).
Ich wollte mit meinem Satz sagen, daß es prinzipiell
wohl funktioniert, auch wenn es eigentlich nicht vor-
gesehen ist.
Post by Stefan Wiens
Denn sed ist ein Stream editor.
Ja, daher auch wohl der Name.

[...]
Post by Stefan Wiens
Post by Marcel Logen
Post by Stefan Wiens
Das "b"-Kommando hat den Zweck,
dass man überall "3" schreiben kann anstatt rumzurechnen.
Das habe ich leider noch nicht verstanden.
Alle Ziffern "3" beziehen sich auf die Fragestellung (ich habe "13" auf
"3" reduziert). Sonst müsste man halt "4${" schreiben und die Shell oder
wer auch immer müsste es ausrechnen. "b3" springt zum Ende des Scripts,
denn bis dahin sin noch keine auszugebenden Daten gesammelt worden.
Das Zum-Ende-Springen hatte mich zunächst ein wenig ir-
ritiert, aber jetzt ist es mir etwas klarer geworden.

Marcel
--
╭─╮ ╭───────────╮ ╭──╮ ╭─────╮ ╭──────────╮ ╭────
─╯ ╰─╮ ╰────╮ ╰──╯ │ ╭─╮ ╭─╯ ╭──╯ ╰────────╮ ╰─╮ │
╰──╮ ╭─╯ ╰─╯ │ ╰─╮ ╰─╮ ╭─╮ ╭───╯ ╰──────╯
╰──╯ ╰────╯ ╰─╯ ╰───────╯
Stefan Wiens
2021-03-03 20:25:34 UTC
Permalink
Post by Marcel Logen
<http://sed.sourceforge.net/grabbag/scripts/dc.sed>?
Bei dem Skript ist das Lesen gefährlicher als das Ausführen.

Ich gestehe, dass ich es nicht bis in alle Winkel nachvollzogen habe.
Aber Addieren mit sed habe ich selbst probiert.
--
Stefan
Helmut Waitzmann
2021-02-22 01:26:05 UTC
Permalink
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen.
Ich vermute, dass es geht.  Schau mal in der «sed»‐Dokumentation die
Beispiele für «head» und «tail» an.  Wenn Du die kombinierst, kommt
vermutlich ungefähr das heraus, was Du brauchst. 
| ./sigqp2 | cat -vET > "$tmep" &&
| head -n 13 "$tmep" && printf '%s\n' '[...]' &&
| tail -n 13 "$tmep"
Wenn «./sigqp2» weniger als 26 Zeilen ausgibt, sind die mittleren
Zeilen doppelt dabei (Extremfall:  Sind es höchstens 13 Zeilen, wird
die ganze Ausgabe doppelt ausgegeben).  Ein «sed»‐Aufruf könnte das
vermeiden.  Eine andere Idee wäre «awk». 


Crosspost & Followup-To: de.comp.os.unix.shell
Marcel Logen
2021-02-22 11:16:40 UTC
Permalink
Post by Helmut Waitzmann
Dabei wollte ich zu Demo- und Test-Zwecken nur die er-
sten 13 und die letzten 13 Zeilen des Ergebnisses aus-
geben.
Zunächst hatte ich es mit "sed" versucht. Das scheint
aber nicht zu gehen.
Ich vermute, dass es geht.  Schau mal in der «sed»‐Dokumentation die
Beispiele für «head» und «tail» an.  Wenn Du die kombinierst, kommt
vermutlich ungefähr das heraus, was Du brauchst. 
Danke. Ich habe
<https://www.gnu.org/software/sed/manual/sed.html#head>
(7.15 und 7.16) gefunden.

Damit - oder mit Stefans Vorschlag - sollte es dann gehen.
Post by Helmut Waitzmann
| ./sigqp2 | cat -vET > "$tmep" &&
| head -n 13 "$tmep" && printf '%s\n' '[...]' &&
| tail -n 13 "$tmep"
Wenn «./sigqp2» weniger als 26 Zeilen ausgibt, sind die mittleren
Zeilen doppelt dabei (Extremfall:  Sind es höchstens 13 Zeilen, wird
die ganze Ausgabe doppelt ausgegeben).  Ein «sed»‐Aufruf könnte das
vermeiden.  Eine andere Idee wäre «awk». 
./sigqp2 gibt so zwischen 30 und 45 Zeilen aus. Da wird
das Problem also nicht auftreten.

Über awk hatte ich auch nachgedacht, aber auf die Idee,
alles erst mal einzulesen, wie Urs das vorschlägt, war
ich nicht gekommen.

Danke an alle, die sich beteiligt haben!

Marcel
--
──╮ ╭─╮ ╭───╮ ╭───────╮ ╭──────╮ ╭──────╮ ╭───
╰─╯ ╰─╮ ╭────╯ │ ╭─╯ ╭────╯ ╰──╮ ╰──╯ ╭───╯ ╭─╯
╭─────╯ ╭─╯ ╭─────╯ ╰──╮ ╰───────╮ ╭──────╮ ╰───╮ ╭──╯ ╭───╯
╰────────╯ ╰───────────╯ ╰─╯ ╰──────╯ ╰────╯
Urs Janßen
2021-02-22 08:50:17 UTC
Permalink
Post by Marcel Logen
Ich hatte auch an "awk" gedacht, bin damit aber
auch nicht weitergekommen.
quick'n'drity (merkt sich viel zu viel):

awk '{l[NR]=$0}END{for(i=1;i<j;i++){if(i<=13||i>=(NR-13)){print l[i]}}}'
Urs Janßen
2021-02-22 08:52:33 UTC
Permalink
Post by Marcel Logen
Ich hatte auch an "awk" gedacht, bin damit aber
auch nicht weitergekommen.
quick'n'drity (merkt sich viel zu viel):

awk '{l[NR]=$0}END{for(i=1;i<NR;i++){if(i<=13||i>=(NR-13)){print l[i]}}}'
Stefan Wiens
2021-02-22 11:24:07 UTC
Permalink
Post by Urs Janßen
Post by Marcel Logen
Ich hatte auch an "awk" gedacht, bin damit aber
auch nicht weitergekommen.
awk '{l[NR]=$0}END{for(i=1;i<NR;i++){if(i<=13||i>=(NR-13)){print l[i]}}}'
Sparsamer und ohne Off-by-one-Error:

awk '
BEGIN{nh=3; nt=3}
{
l[NR]=$0
if(NR>nh+nt)
{delete l[NR-nt]}
}
END{for(i=1;i<=NR;i++)
{if(i<=nh||i>(NR-nt))
{print l[i]}}}'
--
Stefan
Urs Janßen
2021-02-22 11:44:33 UTC
Permalink
Post by Stefan Wiens
awk '
BEGIN{nh=3; nt=3}
{
l[NR]=$0
if(NR>nh+nt)
{delete l[NR-nt]}
}
END{for(i=1;i<=NR;i++)
{if(i<=nh||i>(NR-nt))
{print l[i]}}}'
ich war bei

awk 'BEGIN{n=13}{l[NR]=$0;if(NR>2*n){delete l[NR-n]}}END{for(i in l){print l[i]}}'
Stefan Wiens
2021-02-22 12:33:41 UTC
Permalink
Post by Urs Janßen
ich war bei
awk 'BEGIN{n=13}{l[NR]=$0;if(NR>2*n){delete l[NR-n]}}END{for(i in l){print l[i]}}'
Bei "for (variable in array)" ist die Reihenfolge undefiniert.
--
Stefan
Christian Weisgerber
2021-02-22 17:35:35 UTC
Permalink
Post by Stefan Wiens
awk '
BEGIN{nh=3; nt=3}
{
l[NR]=$0
if(NR>nh+nt)
{delete l[NR-nt]}
}
END{for(i=1;i<=NR;i++)
{if(i<=nh||i>(NR-nt))
{print l[i]}}}'
Hier eine Variante mit Ringpuffer, die sich also nur maximal so
viele Zeilen merkt, wie am Ende auszugeben sind. Beispielhaft mit
5 Kopf- und 13 Schwanzzeilen.

------------------->
#!/usr/bin/awk -f

BEGIN {
head = 5
tail = 13
}

{
if (NR <= head)
print $0
else
buf[i] = $0
i = (i + 1) % tail
}

END {
for (j = 0; j < tail; j++) {
if (i in buf)
print buf[i]
i = (i + 1) % tail
}
}
<-------------------
--
Christian "naddy" Weisgerber ***@mips.inka.de
Stefan Wiens
2021-02-22 19:42:38 UTC
Permalink
Post by Christian Weisgerber
Post by Stefan Wiens
awk '
BEGIN{nh=3; nt=3}
{
l[NR]=$0
if(NR>nh+nt)
{delete l[NR-nt]}
}
END{for(i=1;i<=NR;i++)
{if(i<=nh||i>(NR-nt))
{print l[i]}}}'
Hier eine Variante mit Ringpuffer, die sich also nur maximal so
viele Zeilen merkt, wie am Ende auszugeben sind. Beispielhaft mit
5 Kopf- und 13 Schwanzzeilen.
------------------->
#!/usr/bin/awk -f
BEGIN {
head = 5
tail = 13
}
{
if (NR <= head)
print $0
else
buf[i] = $0
i = (i + 1) % tail
}
END {
for (j = 0; j < tail; j++) {
if (i in buf)
print buf[i]
i = (i + 1) % tail
}
}
<-------------------
Anders als bei meiner Version (mit delete) wird da aber (bis auf
die paar Zeilen am Anfang) die vollständige Eingabe in das
Array buf ge"slurped". Ich nehme an, dass Urs das auch so meinte.
--
Stefan
Stefan Wiens
2021-02-22 20:28:03 UTC
Permalink
[Supersede wegen Meinungsänderung]
Post by Christian Weisgerber
Post by Stefan Wiens
awk '
BEGIN{nh=3; nt=3}
{
l[NR]=$0
if(NR>nh+nt)
{delete l[NR-nt]}
}
END{for(i=1;i<=NR;i++)
{if(i<=nh||i>(NR-nt))
{print l[i]}}}'
Hier eine Variante mit Ringpuffer, die sich also nur maximal so
viele Zeilen merkt, wie am Ende auszugeben sind. Beispielhaft mit
5 Kopf- und 13 Schwanzzeilen.
------------------->
#!/usr/bin/awk -f
BEGIN {
head = 5
tail = 13
}
{
if (NR <= head)
print $0
else
buf[i] = $0
i = (i + 1) % tail
}
END {
for (j = 0; j < tail; j++) {
if (i in buf)
print buf[i]
i = (i + 1) % tail
}
}
<-------------------
Entgegen meiner vorschnellen Äußerung wird da nichts ge"slurpt", sondern
es funktioniert.
--
Stefan
Stefan Wiens
2021-02-23 00:12:00 UTC
Permalink
Post by Christian Weisgerber
Hier eine Variante mit Ringpuffer, die sich also nur maximal so
viele Zeilen merkt, wie am Ende auszugeben sind. Beispielhaft mit
5 Kopf- und 13 Schwanzzeilen.
------------------->
#!/usr/bin/awk -f
BEGIN {
head = 5
tail = 13
}
{
if (NR <= head)
print $0
else
buf[i] = $0
i = (i + 1) % tail
}
END {
for (j = 0; j < tail; j++) {
if (i in buf)
print buf[i]
i = (i + 1) % tail
}
}
<-------------------
Bei awk, wo es ja nur assoziative Arrays gibt, könnte man diskutieren,
ob man lieber existierende Indices wiederverwenden sollte oder
stattdessen neue Indices und die nicht mehr benötigten deleten.
--
Stefan
Lesen Sie weiter auf narkive:
Loading...