[gelöst] Verständnisproblem beim Quoting

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
TomL

[gelöst] Verständnisproblem beim Quoting

Beitrag von TomL » 28.02.2020 19:34:50

Moin @ all

In meinem kleinem Script, welches mich bei der Einrichtung von fremden WLAN-Accesspoints und Verbindungen dorthin unterstützt, hatte ich an einer Stelle im Code sinngemäß diese Zeile stehen:

if [ -z "$(iw dev $dev scan | grep -i ssid: $ssid)" ] ....usw

Das hat bislang immer prima funktioniert.... zufälligerweise leider aber nur deswegen, weil ich bisher noch nie über eine 'falsche' SSID gestolpert bin. Und die hatte ich erstmalig gestern: "Fritz!Box 6490 Cable" ... mit Blanks und ! :roll:

Ist klar... damit kam der zuerst der obige grep nicht klar, und anschließend starb auch die gleichnamige Conf für wpa-supplicant. Ich habe dann nach stundenlangen :facepalm: experiementiren eher zufällig diese Lösung gefunden, die auf einmal funktioniert hat:
if [ -z "$(iw dev $dev scan | grep -i "ssid: $ssid")" ] ....usw

Das gleiche funktioniert dann auch mit wpa_supplicant:
wpa_supplicant -B -i $dev -c /etc/wpa_supplicant/"$ssid".conf

Bei wpa_supplicant verstehe ich die Lösung, weil es keine vorher öffnenden und hinterher schließenden Quots gibt.... aber beim obigen grep gibts die. Ich bin deshalb nicht auf diese Lösung gekommen, weil ich unterstellt habe, dass das erste innere " das Schließen des ersten äußeren " bedeutet... also bei Quots nicht nach der Klammer-Regelung, sondern etwa so:
"eins auf + eins zu" "zwei auf + zwei zu"

... was aber anscheinend gar nicht zutrifft. Anscheinend wird die Syntax nach Klammer-Regelung
"außen auf "innen auf + innen zu" außen zu"

interpretiert. Ich bin jetzt leidlich irritiert, wie da die tatsächliche Verarbeitung aussieht. Hat da jemand mehr Wissen?
Zuletzt geändert von TomL am 01.03.2020 11:34:45, insgesamt 1-mal geändert.

wanne
Moderator
Beiträge: 7547
Registriert: 24.05.2010 12:39:42

Re: Verständnisproblem beim Quoting

Beitrag von wanne » 28.02.2020 19:59:33

Die bash hat leider extrem viele ausnahmen, die dafür sorgen dass das Ding meistens das macht was der User will. Das führt zu einer recht komplexen Syntax mit diversen Spezialfällen.
Das ist so eine Bash-Spezialität...

"$( )" wird wie "$@"als ein geschlossener Ausdruck zu verstehen sein und hat glaube ich erst mal nichts mit "" und einem gekapselten $( ) zu tun. Auch wenn es sich sehr ähnlich verhält.
So wie $() nichts mit einem $ und einem () zu tun hat...

Aber selbst wenn es nicht so wäre: Was im $() steht hat die äußere Shell nicht zu interessieren. Der sucht immer zuerst nach der schließenden Klammer. Der teil wird dann von einer eigenen Bash interpretiert.

Du hast also in der Klammer
iw dev $dev scan | grep -i "ssid: $ssid"
Und außerhalb:
if [ -z "Fritz!Box XXX" ]
rot: Moderator wanne spricht, default: User wanne spricht.

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

Re: Verständnisproblem beim Quoting

Beitrag von Meillo » 28.02.2020 21:10:55

wanne hat geschrieben: ↑ zum Beitrag ↑
28.02.2020 19:59:33
Die bash hat leider extrem viele ausnahmen, die dafür sorgen dass das Ding meistens das macht was der User will. Das führt zu einer recht komplexen Syntax mit diversen Spezialfällen.
Das klingt etwas negativer als ich es sagen wuerde. In den Randbereichen der Syntax wird's zwar oefters mal interessant, aber mit ein paar wenigen Regeln kommt man normalerweise ziemlich weit.


$() funktioniert so, dass du darin eine normale Kommandozeile reinsetzen kannst -- genau so wie sie ist -- und deren Ausgabe dann an diese Stelle ersetzt wird, in der gleichen Weise, wie wenn die Ausgabe in einer Variable waere.

Dieser Befehl:

Code: Alles auswählen

iw dev $dev scan | grep -i "ssid: $ssid"
kann 1:1 so in eine Kommandosubstitution ($()) gesetzt werden.

Wenn die Ausgabe der Kommandosubstitution dann fuer den umgebenden Befehl als ein Wort aufgefasst werden soll (z.B. wenn Whitespace enthalten ist), dann muss die Kommandosubstitution mit Double-Quotes umgeben werden, weil sie andernfalls nochmal in Worte gesplittet wird.

Als Faustregel sollte man in der Shell alle Variablenexpansionen und alle Kommandosubstitution in Double-Quotes setzen! Nur wenn man das explizit nicht will, muss man sie weglassen. In obigem Beispiel sollte als `$dev' auch gequotet sein, und sei es nur deshalb, weil man fast immer das Verhalten von gequoteten Variablenexpansionen haben will, was im ungequoteten Fall nur zufaellig gleich ist, wenn kein Whitespace enthalten ist.

In dieser Hinsicht ist die Shell tatsaechlich anders als die meisten Programmiersprachen ... aber sie ist auf ihre Weise (zumeist) einheitlich, bloss halt ungewohnt.


$() kann man schachteln. Sie funktionieren dann automatisch richtig.

Quotes kann man nicht schachteln (weil es keinen Unterschied zwischen oeffnendem und schliessendem Quote gibt). (Im Gegensatz zu m4-Macros, im Uebrigen, wo ` und ' verwendet wird.)

Sowas geht also nicht:

Code: Alles auswählen

echo "Er sagte: "Halt!""
Fuer die Shell sind das zwei Woerter:
1) ``echo''
2) ``"Er sagte: "Halt!""''

Beim zweiten Wort wird das Quoting verarbeitet:
Teil 1) ``"Er sagte: "''
Teil 2) ``Halt!''
Teil 3) ``""'' (d.h. ein leerer String)

An `echo' wird dann das Argument ``Er sagte: Halt!'' uebergeben.

Anders saehe es in dem Fall aus:

Code: Alles auswählen

echo "Er sagte: "Sofort Anhalten!""
Hier sind es zwei Woerter:
1) ``"Er sagte: "Sofort''
2) ``Anhalten!""'

Den Unterschied merkt man, wenn man z.B. alle Leerzeichen verdoppelt:

Code: Alles auswählen

$ echo "Er  sagte:  "Sofort  Anhalten!""
Er  sagte:  Sofort Anhalten!
Innerhalb der Quotes wird der Whitespace bewahrt, zwischen seinen Argumentengibt echo immer genau ein Leerzeichen aus.


Wenn man nun aber eine Kommandosubstitution (oder eine Subshell) verwendet, dann steigt man damit eine Ebene tiefer. Das innerhalb der Klammern hat nichts mehr mit dem ausserhalb der Klammern zu tun. Ausgehend von diesem Befehl:

Code: Alles auswählen

if [ -z "$(iwvdrv "$dev" scan | grep -i "ssid: $ssid")" ] ; then ...
... mal eine Zerlegung nach Ebenen:

Code: Alles auswählen

if                                                        ; then ...
   [ -z "                                             " ]
         $(                                          )
           iwvdrv "    " scan |
                   $dev
                                grep -i "           "
                                         ssid: $ssid
(Mir geht es hier nicht um hundertprozentige Korrektheit, sondern um Anschaulichkeit.)

Quotes sind jeweils nur auf ihrere Ebene relevant. Man sieht schoen, dass die Quotes auf Ebene 2 nichts mit denen auf Ebene 4 oder 6 zu tun haben.



Btw:
"$( )" wird wie "$@"als ein geschlossener Ausdruck zu verstehen sein [...]
"$@" ist ein Sonderfall, der anders funktioniert als alles andere Quoting. (Soviel zu meiner Aussage oben. ;-) )

$* verhaelt sich regelkonform: Alle Argumente werden Space-getrennt hintereinander an diese Stelle gesetzt, dann wird nochmal wortgetrennt.

"$*" verhaelt sich regelkonform: Alle Argumente werden Space-getrennt hintereinander als *ein* Wort an diese Stelle gesetzt.

$@ verhaelt sich identisch zu $*.

"$@" ist ein Sonderfall: Alle Argumente werden, jedes fuer sich separat als ein Wort doublegequotet, an diese Stelle gesetzt.

"$@" hat man eingefuehrt, nachdem man gemerkt hat, dass $* nicht funktioniert, wenn die Argumente Spaces enthalten. Dadurch ist $* so gut wie nutzlos geworden.


Die Unix Shell ist schon sehr speziell was das Wortsplitting angeht, verglichen mit normalen Programmiersprachen. Man muss akzeptieren, dass man fuer sie ein anderes Paradigma lernen muss. Alles in der Shell sind Strings und Stringersetzungen. Das ist wie ein Macroprozessor.

Wenn man diese Idee in sehr viel konsistenter Form erleben will, sollte man sich TCL anschauen. Dort findet man die Vollendung der Textersetzung (ohne die Inkonsistenten der Shell). Und TCL schlaegt dann auch den Bogen bis zu LISP, wo alles Listen sind. ... aber das geht jetzt natuerlich alles sehr weit ueber die eigentliche Frage hinaus. ;-)
Use ed once in a while!

TomL

Re: Verständnisproblem beim Quoting

Beitrag von TomL » 28.02.2020 21:25:12

@meillo

Das waren jetzt interessante Beispiele.... schau Dir mal das Ergebnis in meiner Buster-Bash an:

Code: Alles auswählen

$ echo "Er sagte: "Halt!""
bash: !"": event not found

$ echo "Er sagte: "Halt""
Er sagte: Halt

$ echo "Er sagte: "Halt"!"
Er sagte: Halt!
Das erste Ausrufezeichen-Ergebnis passt zu meiner Beobachtung beim Behandeln des Textes "Fritz!Box 6490 Cable"... welches auch das ! enthält. Fällt Dir dazu was ein?

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

Re: Verständnisproblem beim Quoting

Beitrag von Meillo » 28.02.2020 21:51:52

TomL hat geschrieben: ↑ zum Beitrag ↑
28.02.2020 21:25:12

Code: Alles auswählen

$ echo "Er sagte: "Halt!""
bash: !"": event not found
Das erste Ausrufezeichen-Ergebnis passt zu meiner Beobachtung beim Behandeln des Textes "Fritz!Box 6490 Cable"... welches auch das ! enthält. Fällt Dir dazu was ein?
Das kommt von der History-Expansion der Bash. (Ich verwende eine mksh, die macht sowas nicht.)

Du musst die Ausrufezeichen bzw. die Ersetzung halt quoten.
Use ed once in a while!

TomL

Re: Verständnisproblem beim Quoting

Beitrag von TomL » 29.02.2020 10:49:50

Moin @ all

Jetzt habe ich gerade noch mal erneut ein wenig rumprobiert .... und meine Verwirrung ist gestiegen. Im Moment bin ich ein wenig damit überfordert, eine reproduzierbare korrekte Verarbeitungsregel abzuleiten, insbesondere wegen der letzten beiden Befehle, die beide funktionieren. Wie man am Anfang sieht, behandelt die Bash "!" anders als erwartet, trotz Quots. Der letzte "echo" ist so gedacht als Trace-Ausgabe beim Debuggen und funktioniert trotz diesem merkwürdigen Quoting.

Code: Alles auswählen

# ssid="Fritz!Box 6490 Cable"
    bash: !Box: event not found

# ssid='Fritz!Box 6490 Cable'
# dev=wlan0

# ip link set dev wlan0 up

# iw dev $dev scan | grep -i "ssid: $ssid"
    SSID: Fritz!Box 6490 Cable

# echo $(iw dev $dev scan | grep -i "ssid: $ssid")
    SSID: Fritz!Box 6490 Cable

# echo "$(iw dev $dev scan | grep -i "ssid: $ssid")"
    SSID: Fritz!Box 6490 Cable

# echo "iw dev $dev scan | grep -i "ssid: $ssid""
    iw dev wlxec086b1e82ae scan | grep -i ssid: Fritz!Box 6490 Cable
Die ganzen Probleme sind aufgetaucht, als ich bei meinem Bruder über diese SSID gestolpert bin.... was mir in allen Jahren zuvor nie in solcher Schreibweise begegnet ist.

wanne
Moderator
Beiträge: 7547
Registriert: 24.05.2010 12:39:42

Re: Verständnisproblem beim Quoting

Beitrag von wanne » 29.02.2020 10:55:47

! wird nicht von " " gequotet. dazu braucht es ' '. Ist mir bei SSIDs auch schon böse auf die Füße gefallen. Allerdins so im Jahr 2000 wo wpa_supplicant noch ein bash-hook hatte...
man bash hat geschrieben:Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. When the shell is in posix mode, the ! has no special meaning within double quotes, even when history expansion is enabled.
Kurz in einem Shellscript wird es eventuell tun...
rot: Moderator wanne spricht, default: User wanne spricht.

TomL

Re: Verständnisproblem beim Quoting

Beitrag von TomL » 29.02.2020 12:00:29

wanne hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 10:55:47
Kurz in einem Shellscript wird es eventuell tun...
Darum gehts... soll heissen, es handelt sich um meinen eigenen 'kleinen' Network-Manager, der eben ein Bashscript ist und nach meinem Anspruch idealerweise auch allgemein Bash-Kompatibel sein soll. Insbesondere geht es dabei um die Entscheidung, welche dieser beiden Varianten in meinem Script nun die korrekte wäre.... vor dem Effekt, dass beide funktionieren:

if [ -z "$(iw dev $dev scan | grep -i "ssid: $ssid")" ]; then
if [ -z $(iw dev $dev scan | grep -i "ssid: $ssid") ]; then


Die erste Variante erfüllt die Bedingung "ich prüfe auf einen Text, also quote ich auch den Rückgabetext als ganzes". Aber dieses Konstrukt hat die offene Frage, weil " "" " eben nicht den Klammerregeln von innen nach außen folgen.

Die zweite Variante sieht syntaktisch hinsichtlich des Quotings sauber aus, sie funktioniert auch, aber sie erfüllt nicht die Bedingung, den Rückgabetext als gesamtes zu quoten.

Bei der eigentlichen Problemlösung im Programm geht es darum festzustellen, ob für die bestehenden wpa-supplicant-Confs bzw. für die manuell gewählte am aktuellen Ort überhaupt ein Netz angeboten wird. Möglicherweise kann man sich deswegen einfach für Var 2 entscheiden, weil es am Ende unwichtig ist, ob eine mit Blanks oder Sonderzeichen getrennte SSID textlich kaputt geht, weil ich damit ja nichts weiter anstelle. Bei meinen Fritten-Beispiel bedeutet ja auch die Teil-Rückgabe "Fritz" ist nicht leer, also wurde das gesuchte Netz gefunden... weil ja beim Suchen die vollständige SSID verwendet wurde.

Welches Statement übenehme ich dauerhauft? :roll: Ich tendiere zu zwei, weil für die Rückgabe nur leer oder nicht-leer wichtig ist, ob der String als ganzes unvollständig ist, ist eigentlich egal.

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

Re: Verständnisproblem beim Quoting

Beitrag von Meillo » 29.02.2020 12:58:12

TomL hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 10:49:50

Code: Alles auswählen

# echo "$(iw dev $dev scan | grep -i "ssid: $ssid")"
    SSID: Fritz!Box 6490 Cable
Hier bekommt echo ein Argument. Dieses enthaelt die Ausgabe der Kommandosubstitution. Dieser Befehl ist IMO wie er sein sollte ... nur, dass $dev auch noch gequotet sein sollte. (Der Befehl ist natuerlich ein akademisches Beispiel.)

Code: Alles auswählen

# echo "iw dev $dev scan | grep -i "ssid: $ssid""
    iw dev wlxec086b1e82ae scan | grep -i ssid: Fritz!Box 6490 Cable
Dieser Befehl entspricht meinem meinem ``Sofort Anhalten!''-Beispiel. Echo bekommt zwei Argumente:

1) "iw dev $dev scan | grep -i "ssid:
2) $ssid""

Das ist nicht wie es sein sollte. Echo ueberdeckt nur leider einige Probleme, weil es keinen sichtbaren Unterschied macht, ob man ``echo "foo" "bar"'' oder ``echo "foo bar"'' schreibt. Was hier also richtig zu sein *scheint* ist es gar nicht.
Use ed once in a while!

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

Re: Verständnisproblem beim Quoting

Beitrag von Meillo » 29.02.2020 13:25:29

@wanne: Danke fuer die Info mit der History-Expansion. Mir war nicht bewusst, dass man die Single-Quoten muss. Und verstehe ich das richtig, dass die nur in interaktiven Shells aktiviert ist? Ich bin kein Freund der History-Expansion, insbesondere nicht, dass sie automatisch aktiviert ist. Nur wenige Personen nutzen sie tatsaechlich -- sie hat schon einen Wert (fuer die wenigen die sie aktiv nutzen), aber sie sorgt fuer mehr Irritationen (fuer die vielen anderen, die keine Ahnung von ihr haben). Ausserdem verhaelt sich die Shell unterschiedlich wenn man den Befehl im Script oder interaktiv ausfuehrt. Sowas verstoesst immer gegen das Principle of Least Surprise. Nur wenn der Gegenwert gross genug ist, sollte man sowas eingehen. (Z.B. `ls' vs. `ls|cat')

TomL hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 12:00:29
Insbesondere geht es dabei um die Entscheidung, welche dieser beiden Varianten in meinem Script nun die korrekte wäre.... vor dem Effekt, dass beide funktionieren:

if [ -z "$(iw dev $dev scan | grep -i "ssid: $ssid")" ]; then
if [ -z $(iw dev $dev scan | grep -i "ssid: $ssid") ]; then


Die erste Variante erfüllt die Bedingung "ich prüfe auf einen Text, also quote ich auch den Rückgabetext als ganzes".
Ja.
Aber dieses Konstrukt hat die offene Frage, weil " "" " eben nicht den Klammerregeln von innen nach außen folgen.
Warum denn nicht? Schau dir nochmal mein Beispiel mit den Ebenen an. (Tipp: $() oeffet eine neue Ebene.)
Die zweite Variante sieht syntaktisch hinsichtlich des Quotings sauber aus,
Weniger Quoting heisst nicht, dass es korrekter ist. ;-)
sie funktioniert auch,
Funktioniert sie zufaellig oder weil sie korrekt ist?
aber sie erfüllt nicht die Bedingung, den Rückgabetext als gesamtes zu quoten.
Darum funktioniert sie bei mir auch nicht:

Code: Alles auswählen

$ if [ -z $(echo "ssid: Fritz!Box") ]; then echo true; fi    
mksh: [: Fritz!Box: unexpected operator/operand
(Ich habe kein `iw', darum mit echo.)

In meiner Bash ebenso:

Code: Alles auswählen

$ if [ -z $(echo "ssid: Fritz!Box") ]; then echo true; fi
bash: !Box": event not found

$ if [ -z $(echo "ssid: FritzBox") ]; then echo true; fi
bash: [: ssid:: binary operator expected
Kurzum: Mit Double-Quotes um die Kommandosubstituation ist es korrekt.

Wenn du die History-Expansion loswerden willst, dann musst du nicht-interaktiv testen oder sie mit `set +H' deaktivieren. Siehe:
Manpage bash hat geschrieben: This feature is enabled
by default for interactive shells, and can be disabled using
the +H option to the set builtin command (see SHELL BUILTIN
COMMANDS below). Non-interactive shells do not perform his-
tory expansion by default.
Welches Statement übenehme ich dauerhauft? :roll: Ich tendiere zu zwei, weil für die Rückgabe nur leer oder nicht-leer wichtig ist, ob der String als ganzes unvollständig ist, ist eigentlich egal.
Der Operator `-z' des test-Kommandos ([) ist *unaer*, es ist also nicht egal, ob dahinter noch weitere Argumente kommen, insbesondere koennen die weitere Verwirrung stiften ... und so beispielsweise erzeugt man ungewollt exploitbaren Code, siehe:

Code: Alles auswählen

B-) if [ -z "$(echo "foo")" ]; then echo true; fi         

B-) if [ -z $(echo "foo") ]; then echo true; fi           

B-) if [ -z "$(echo "foo -o x = x")" ]; then echo true; fi

B-) if [ -z $(echo "foo -o x = x") ]; then echo true; fi
true

Ich erklaere gerne noch mehr, wenn du mir nochmal zeigst, wo genau die Verstaendnisprobleme und Unklarheiten noch liegen.
Use ed once in a while!

TomL

Re: Verständnisproblem beim Quoting

Beitrag von TomL » 29.02.2020 14:14:28

Das Problem ist zudem auch abhängig von der Deklaration resp. der Zuweisung des Wertes... schau Dir das mal an:

Code: Alles auswählen

# ssid='Fritz!Box 6490 Cable'
# dev="wlan0"

# echo $(iw dev $dev scan | grep -i "ssid: $ssid")
SSID: Fritz!Box 6490 Cable

# echo $(echo "ssid: $ssid")
ssid: Fritz!Box 6490 Cable

# echo $(echo "ssid: Fritz!Box 6490 Cable")
bash: !Box: event not found

# echo $(echo "ssid: 'Fritz!Box 6490 Cable'")
bash: !Box: event not found
:roll:
funktioniert sie zufaellig oder weil sie korrekt ist?
Ich habe eher das Gefühl, dass dieses folgende Konstrukt zufällig ist, weil eben Teile aus dem Quoting herausgelöst sind und weil nach meinem Verständnis des Quotings semantisch alles aus dem Ruder läuft:

Code: Alles auswählen

if [ -z "$(iw dev $dev scan | grep -i "ssid: $ssid")" ]; then
        +-----------------------------+           +-+
Dieses Beispiel von Dir...

Code: Alles auswählen

if                                                        ; then ...
   [ -z "                                             " ]
         $(                                          )
           iwvdrv "    " scan |
                   $dev
                                grep -i "           "
                                         ssid: $ssid
... was ich so darstellen würde, ...

Code: Alles auswählen

if [ -z "$(iw dev "$dev" scan | grep -i "ssid: $ssid")" ]; then
                  +----+                +-----------+
        +---------------------------------------------+
.... würde hingegen bedeuten, dass die Auflösung des Pakets quasi Klammel-Regel-Konform wäre... nacheinander von innen nach außen. Damit wäre das Problem ja gelöst und es wäre klar, welches Vorgehen das richtige ist. Aber ich habe aus dem bisherigen Verlauf des Threads abgeleitet, dass das eben beim Quoting nicht so gehandhabt wird, *hmmm* wodurch ich jetzt wieder versunsichert bin, was am Ende wirklich zutrifft.
Der Operator `-z' des test-Kommandos ([) ist *unaer*, es ist also nicht egal, ob dahinter noch weitere Argumente kommen, insbesondere koennen die weitere Verwirrung stiften ... und so beispielsweise erzeugt man ungewollt exploitbaren Code, siehe:

*Wow*
... diese Erkenntnis hat mich jetzt erst mal umgehau'n... *boar*... das war mir neu und das muss ich jetzt erst mal verdauen.... ich kann die Konsequenzen auf meinen vorhandenen Code noch gar nicht absehen. :?


Nachtrag:
Nach 'ner viertelstunde drauf rumkauen kommt mir gerade die Idee in den Sinn, dass das vielleicht doch nicht semantisch aus dem Ruder läuft, weil das Gesamt-Statement möglicherweise als 2 Statements betrachtet wird, so in etwa nach diesem Muster:

Code: Alles auswählen

if [ -z "$(                                          )" ]; then
           iw dev "$dev" scan | grep -i "ssid: $ssid"
                  +----+                +-----------+
        +---------------------------------------------+
Wenn das zutreffen würde, also basierend auf der Behandlung durch $(...), käme ich damit als Erklärung bestens zurecht....

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

Re: Verständnisproblem beim Quoting

Beitrag von Meillo » 29.02.2020 16:44:59

Die kurze Antwort:
TomL hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 14:14:28
Nachtrag:
Nach 'ner viertelstunde drauf rumkauen kommt mir gerade die Idee in den Sinn, dass das vielleicht doch nicht semantisch aus dem Ruder läuft, weil das Gesamt-Statement möglicherweise als 2 Statements betrachtet wird, so in etwa nach diesem Muster:

Code: Alles auswählen

if [ -z "$(                                          )" ]; then
           iw dev "$dev" scan | grep -i "ssid: $ssid"
                  +----+                +-----------+
        +---------------------------------------------+
Wenn das zutreffen würde, also basierend auf der Behandlung durch $(...), käme ich damit als Erklärung bestens zurecht....
Tada! :-D Jetzt hast du's geschnallt. :THX:



Hier trotzdem noch ein paar Anmerkungen zum Rest deines Posts.
TomL hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 14:14:28
Das Problem ist zudem auch abhängig von der Deklaration resp. der Zuweisung des Wertes... schau Dir das mal an:

Code: Alles auswählen

# ssid='Fritz!Box 6490 Cable'
# dev="wlan0"

# echo $(iw dev $dev scan | grep -i "ssid: $ssid")
SSID: Fritz!Box 6490 Cable

# echo $(echo "ssid: $ssid")
ssid: Fritz!Box 6490 Cable

# echo $(echo "ssid: Fritz!Box 6490 Cable")
bash: !Box: event not found

# echo $(echo "ssid: 'Fritz!Box 6490 Cable'")
bash: !Box: event not found
:roll:
Immer wenn ein Ausrufezeichen ungequotet oder nur in Double-Quotes da steht, greift die History-Expansion ein. Das betrifft die letzten beiden Faelle.

Der letzte Fall ist insofern interessant, dass die eine Art von Quotes die Sonderbedeutung der anderen aufhebt. Wenn du also ein Single-Quote in einen String packen willst, dann indem du ihn mit Double-Quotes umschliesst, und umgekehrt:

Code: Alles auswählen

$ echo "Er hat's geschnallt."
Er hat's geschnallt.

$ echo '26"-Reifen'
26"-Reifen
Da gibt es die nette Frage, wie man diese Zeichenfolge ausgibt: "'"

Einerseits geht das natuerlich mit Backslashes, aber es geht auch ohne:

Code: Alles auswählen

B-) echo \"\'\"
"'"

B-) echo '"'"'"'"'
"'"
(Man muss das ``nur'' stupide abarbeiten, dann ist es einfach.)

Der Operator `-z' des test-Kommandos ([) ist *unaer*, es ist also nicht egal, ob dahinter noch weitere Argumente kommen, insbesondere koennen die weitere Verwirrung stiften ... und so beispielsweise erzeugt man ungewollt exploitbaren Code, siehe:

*Wow*
... diese Erkenntnis hat mich jetzt erst mal umgehau'n... *boar*... das war mir neu und das muss ich jetzt erst mal verdauen.... ich kann die Konsequenzen auf meinen vorhandenen Code noch gar nicht absehen. :?
Das ist ein typisches Angriffsmuster, das beispielsweise auch bei SQL beliebt ist. Man kann es verhindern, wenn man dafuer sorgt, dass das Eingegebene als genau ein Wert genutzt wird und keinen zusaetzlichen Code erzeugen kann. Dafuer sorgen hier die Quotes. (Bei SQL waeren es Prepared Statements.)
Use ed once in a while!

TomL

Re: Verständnisproblem beim Quoting

Beitrag von TomL » 01.03.2020 11:42:03

Meillo hat geschrieben: ↑ zum Beitrag ↑
29.02.2020 16:44:59
Tada! Jetzt hast du's geschnallt.
:D
Jau, und ich Danke Dir für die Hilfe. :hail:

Mein kleines Problem bestand in der Annahme, dass für das gesamte Statement auch eine gesamte Verarbeitungslogik zugrunde gelegt wird. Aber wie sich nun herausgestellt hat findet die Verarbeitung innerhalb von $(...) separat von dem außerhalb liegenden Anteil statt. Wieder was dazu gelernt.
Aber das größere Problem ist, was man gar nicht mehr verleugnen kann, dass die bash so ein komplexes 'Teil' ist, dass es für einen Laien wie mich mit diesem Detail-Reichtum kaum noch möglich ist, an mehr als nur an der Oberfläche zu kratzen. :roll:

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

Re: [gelöst] Verständnisproblem beim Quoting

Beitrag von Meillo » 01.03.2020 12:23:29

So manches Mal im Leben ist weniger mehr. ;-)

Viel moderne Software ist voellig ueberladen. Auch die Bash ist ein riesen Ding. Das kann schon hilfreich sein, in manchen Faellen, aber halt nicht in den meisten Faellen. Es ist eine Fehlannahme, das One-fits-all funktioniert. Komplexitaet (d.h. Fehleranfaelligkeit, erhoehter Verstaendnisaufwand, ...) betrifft nicht nur den Code den man selber schreibst, sondern auch die Systeme die man nutzt. Das wird zu selten gesehen.



Dass du diese Situation hier nicht sofort verstanden hast, ist schade, weil es darauf hindeutet, dass die Konzepte zu schwierig sind. Vielleicht ist das aber noetig -- das will ich hier nicht eroertern. Es zeigt aber auch, dass andere Programmiersprachen andere Konzepte haben, die man neu lernen muss. Man kann nicht automatisch von einem Kontext in den anderen uebertragen. Und auch wenn es mehr Aufwand erfordert, Wissen aufzubauen the hard way ist gar nicht so schlecht. Deine Investition in dieses Verstaengnis war eine gute. Es wird sehr viel langfristiger und tiefer sein als wenn der Thread nach zwei Antworten erledigt gewesen waere. Was ich sagen will: Es lohnt sich Zeit hineinzuinvestieren und es (mit Hilfe) selber herauszufinden. Das ist viel besser als von aussen vorgegebenes Wissen einfach nur zu akzeptieren.

In diesem Sinne: Weiter so! :-)
Use ed once in a while!

Antworten