Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
-
HansD
- Beiträge: 234
- Registriert: 29.04.2013 15:47:29
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Berlin
Beitrag
von HansD » 01.05.2018 00:58:36
Hier im Forum hat mir jemand einen guten Hinweis gegeben, wie ich eine Kommandoausgabe an ein anderes Kommando weiterleiten könne, wenn ich über einer Tastatur kein Pipe-Zeichen schreiben kann. Dabei ist ein Randproblem aufgetaucht, das ich gerne solide verstehen möchte.
debianforum.de/forum/viewtopic.php?p=1172987#p1172987
Code: Alles auswählen
hansd@linux-system: Downloads $ less <<< $(cat /etc/passwd) | wc -l
1
hansd@linux-system: Downloads $ less <<< "$(cat /etc/passwd)" | wc -l
53
Wie man auch auf dem im Folgendem verlinkten Sccreenshot sehen kann, "verschwinden" die Umbrüche, wenn man die Kommandoausgabe $(...) nicht quotet.
http://i.imgur.com/9Q3EQxgm.png
Ist das,
wie RobertDebiannutzer vermutet,
nur ein Problem etwas älterer Versionen der bash oder ist das verschiedene Verhalten anders zu erklären?
Ich erinnere mich in diesem Zusammenhang auch vage an Parameter von
find und
grep, mit denen man das Zeilenende speziell markiert, durch ein Nullzeichen, wenn ich mich richtig erinnere.
-
tobo
- Beiträge: 2336
- Registriert: 10.12.2008 10:51:41
Beitrag
von tobo » 01.05.2018 15:35:52
HansD hat geschrieben: 01.05.2018 00:58:36
Ist das,
wie RobertDebiannutzer vermutet,
nur ein Problem etwas älterer Versionen der bash oder ist das verschiedene Verhalten anders zu erklären?
Ob das jetzt ein Problem ist, das weiß ich nicht. Jedenfalls liegt es definitiv an der älteren bash. Getestet mit bash-static aus Jessie und bash aus Stretch:
Code: Alles auswählen
$ seq 10 > t.txt
4.3-11$ od -c <<< $(cat t.txt)
0000000 1 2 3 4 5 6 7 8
0000020 9 1 0 \n
0000025
4.3-11$ od -c <<< "$(cat t.txt)"
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
4.4-12$ od -c <<< $(cat t.txt)
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
4.4-12$ od -c <<< "$(cat t.txt)"
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
Aus der manpage:
bash 4.4-12 hat geschrieben:Here Strings
A variant of here documents, the format is:
[n]<<<word
The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Pathname expansion and word splitting are not performed. The result is supplied as a single string, with a newline appended, to the command on its standard input (or file descriptor n if n is specified).
rc verhält sich übrigens so wie die alte bash und ich bin mir auch nicht sicher, ob das wirklich falsch ist!?
-
HansD
- Beiträge: 234
- Registriert: 29.04.2013 15:47:29
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Berlin
Beitrag
von HansD » 03.05.2018 23:10:11
Interessante Antwort. Habe mir aus diesem Anlaß wieder das Kommando
od angeguckt.
Inzwischen meine ich, es hat vor allem mit der Klammerung "
$( ... )" zu tun, weil:
Code: Alles auswählen
$ bash --version
GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu)
[...]
$ od -c <<< $(cat sequence)
0000000 1 2 3 4 5 6 7 8
0000020 9 1 0 \n
0000025
$ od -c <<< "$(cat sequence)"
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
$ od -c <<< cat sequence
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
-
Meillo
- Moderator
- Beiträge: 9227
- Registriert: 21.06.2005 14:55:06
- Wohnort: Balmora
-
Kontaktdaten:
Beitrag
von Meillo » 03.05.2018 23:36:10
tobo hat geschrieben: 01.05.2018 15:35:52
Code: Alles auswählen
$ seq 10 > t.txt
4.3-11$ od -c <<< $(cat t.txt)
0000000 1 2 3 4 5 6 7 8
0000020 9 1 0 \n
0000025
4.3-11$ od -c <<< "$(cat t.txt)"
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
4.4-12$ od -c <<< $(cat t.txt)
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
4.4-12$ od -c <<< "$(cat t.txt)"
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
[...]
rc verhält sich übrigens so wie die alte bash und ich bin mir auch nicht sicher, ob das wirklich falsch ist!?
Das Verhalten der Bash-4.3 erscheint mir stimmig zu den Konzepten der POSIX Shell zu sein, waehrend das der Bash-4.4 mit ihnen kollidiert.
Dieser letzte Fall hier ist nun voellig seltsam:
HansD hat geschrieben: 03.05.2018 23:10:11
Code: Alles auswählen
$ bash --version
GNU bash, Version 4.3.48(1)-release (x86_64-pc-linux-gnu)
[...]
$ od -c <<< cat sequence
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
Es gibt keine Kommandosubstitution und doch wird das Wort ausgefuehrt, und nicht nur das Wort, sondern zwei Worte. Fehlen da Backticks? Ich kann kaum glauben, dass das so funktionieren kann.
Use ed once in a while!
-
tobo
- Beiträge: 2336
- Registriert: 10.12.2008 10:51:41
Beitrag
von tobo » 04.05.2018 00:47:19
Meillo hat geschrieben: 03.05.2018 23:36:10
Code: Alles auswählen
$ od -c <<< cat sequence
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
Es gibt keine Kommandosubstitution und doch wird das Wort ausgefuehrt, und nicht nur das Wort, sondern zwei Worte. Fehlen da Backticks? Ich kann kaum glauben, dass das so funktionieren kann.
cat verschwindet mit stdin (temporäre Datei?!), sequence (ff.) ist dann ein normaler Datei-Parameter. Vergleiche:
Code: Alles auswählen
$ set -x
$ od -c <<< Auto Waschanlage sequence
## 69 : od -c Waschanlage sequence
od: Waschanlage: No such file or directory
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
Und das würde ich eigentlich schon bei der ersten Ausgabe erwarten:
Code: Alles auswählen
$ od -c - <<< Auto Waschanlage sequence
## 70 : od -c - Waschanlage sequence
od: Waschanlage: No such file or directory
0000000 A u t o \n 1 \n 2 \n 3 \n 4 \n 5 \n 6
0000020 \n 7 \n 8 \n 9 \n 1 0 \n
0000032
-
Meillo
- Moderator
- Beiträge: 9227
- Registriert: 21.06.2005 14:55:06
- Wohnort: Balmora
-
Kontaktdaten:
Beitrag
von Meillo » 04.05.2018 08:48:41
Danke. Jetzt habe ich's auch kapiert.
Der String ``cat'' kommt auf stdin, was aber ignoriert wird, weil zudem die Datei `sequence' uebergeben wird. od(1) verarbeitet nur die Datei und versucht gar nicht erst stdin zu lesen. Das ist wie wenn man ``<<< cat'' ganz weggelassen haette.
Use ed once in a while!
-
HansD
- Beiträge: 234
- Registriert: 29.04.2013 15:47:29
- Lizenz eigener Beiträge: MIT Lizenz
- Wohnort: Berlin
Beitrag
von HansD » 04.05.2018 17:25:18
Meillo hat geschrieben: 04.05.2018 08:48:41
Danke. Jetzt habe ich's auch kapiert.
Der String ``cat'' kommt auf stdin, was aber ignoriert wird, weil zudem die Datei `sequence' uebergeben wird. od(1) verarbeitet nur die Datei und versucht gar nicht erst stdin zu lesen. Das ist wie wenn man ``<<< cat'' ganz weggelassen haette.
Ich sehe, was passiert, und habe es in zig Varianten ausprobiert; aber richtig verstanden habe ich es noch nicht.
Sowohl cat als auch die Datei sequence kommen ja über stdin zu od. Wenn ich aber od normal benutze, passiert Folgendes:
Code: Alles auswählen
$ ls -1
sequence
test1
$ more *
::::::::::::::
sequence
::::::::::::::
1
2
3
4
5
6
7
8
9
10
::::::::::::::
test1
::::::::::::::
eins
zwei
drei
$ od -c -An test1 sequence
e i n s \n z w e i \n d r e i \n \n
1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
9 \n 1 0 \n
Ich kann schreiben, was ich will, das erste "Wort" wird bei der Übergabe durch "<<<" ignoriert.
Code: Alles auswählen
$ od -c <<< ls sequence
0000000 1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n
0000020 9 \n 1 0 \n
0000025
$ cat <<< ls sequence
1
2
3
4
5
6
7
8
9
10
$ cat <<< . test1
eins
zwei
drei
Ok, während ich das eben geschrieben und nochmals ausprobiert habe, habe ich es verstanden.
"od -c <<< cat dateiname ..." bewirkt dasselbe wie
"cat dateiname ... | od -c" und bedeutet, dass die Ausgabe, das Ergebnis des Kommandos "cat dateiname ..." an das Programm od übergeben wird. Deswegen sieht es so aus als würde od das erste Wort ignorieren, das aber nie bei ihm ankommt, weil bash das erste Wort als Kommandoname versteht.
-
owl102
Beitrag
von owl102 » 04.05.2018 17:45:05
HansD hat geschrieben: 04.05.2018 17:25:18
Sowohl cat als auch die Datei sequence kommen ja über stdin zu od.
Nein, nur die Zeichenkette "cat".
Das ist identisch zu
genauso, wie
identisch ist mit
oder
Ich kann schreiben, was ich will, das erste "Wort" wird bei der Übergabe durch "<<<" ignoriert.
Ja, weil es über stdin an od übergeben wird, wenn aber od eine Dateiangabe bekommt, ignoriert es stdin.
"od -c <<< cat dateiname ..." bewirkt dasselbe wie
"cat dateiname ... | od -c"
Nein, es bewirkt dasgleiche wie
-
tobo
- Beiträge: 2336
- Registriert: 10.12.2008 10:51:41
Beitrag
von tobo » 04.05.2018 17:48:24
HansD hat geschrieben: 04.05.2018 17:25:18
Ich kann schreiben, was ich will, das erste "Wort" wird bei der Übergabe durch "<<<" ignoriert.
Dann hast du dir meine beiden Beispiele darüber nicht richtig angeschaut.
Es fehlte ein abschließender "-", um od klarzumachen, dass jetzt die Eingabe von stdin (funktioniert auch andersrum mit stdout) kommt/respekiert werden soll.
Ok, während ich das eben geschrieben und nochmals ausprobiert habe, habe ich es verstanden.
"od -c <<< cat dateiname ..." bewirkt dasselbe wie
"cat dateiname ... | od -c" und bedeutet, dass die Ausgabe, das Ergebnis des Kommandos "cat dateiname ..." an das Programm od übergeben wird.
Es bewirkt vielleicht dasselbe. "od -c <<< cat dateiname" ist wirkweise dasselbe wie "od -c dateiname". Siehst du auch oben nach dem Einschalten von set -x.