Warum wirkt das Quoting in diesem Fall?

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
HansD
Beiträge: 234
Registriert: 29.04.2013 15:47:29
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Berlin

Warum wirkt das Quoting in diesem Fall?

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

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von tobo » 01.05.2018 15:35:52

HansD hat geschrieben: ↑ zum Beitrag ↑
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

Re: Warum wirkt das Quoting in diesem Fall?

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

Benutzeravatar
Meillo
Moderator
Beiträge: 9227
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von Meillo » 03.05.2018 23:36:10

tobo hat geschrieben: ↑ zum Beitrag ↑
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: ↑ zum Beitrag ↑
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

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von tobo » 04.05.2018 00:47:19

Meillo hat geschrieben: ↑ zum Beitrag ↑
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

Benutzeravatar
Meillo
Moderator
Beiträge: 9227
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Warum wirkt das Quoting in diesem Fall?

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

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von HansD » 04.05.2018 17:25:18

Meillo hat geschrieben: ↑ zum Beitrag ↑
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

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von owl102 » 04.05.2018 17:45:05

HansD hat geschrieben: ↑ zum Beitrag ↑
04.05.2018 17:25:18
Sowohl cat als auch die Datei sequence kommen ja über stdin zu od.
Nein, nur die Zeichenkette "cat".

Code: Alles auswählen

od -c <<< ls sequence
Das ist identisch zu

Code: Alles auswählen

od -c sequence <<< "ls"
genauso, wie

Code: Alles auswählen

echo "Hallo" > datei "Echo"
identisch ist mit

Code: Alles auswählen

echo "Hallo" "Echo" > datei
oder

Code: Alles auswählen

echo > datei "Hallo" "Echo"
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

Code: Alles auswählen

echo "cat" | od -c dateiname

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: Warum wirkt das Quoting in diesem Fall?

Beitrag von tobo » 04.05.2018 17:48:24

HansD hat geschrieben: ↑ zum Beitrag ↑
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.

Code: Alles auswählen

$ od -c - <<< ls sequence
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.

Antworten