[gelöst] Verständnisproblem beim Quoting
[gelöst] Verständnisproblem beim Quoting
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 !
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 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?
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 !
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 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.
Re: Verständnisproblem beim Quoting
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" ]
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.
Re: Verständnisproblem beim Quoting
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.wanne hat geschrieben:28.02.2020 19:59:33Die 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.
$() 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"
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!""
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!""
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!
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 ...
Code: Alles auswählen
if ; then ...
[ -z " " ]
$( )
iwvdrv " " scan |
$dev
grep -i " "
ssid: $ssid
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:
"$@" ist ein Sonderfall, der anders funktioniert als alles andere Quoting. (Soviel zu meiner Aussage oben. )"$( )" wird wie "$@"als ein geschlossener Ausdruck zu verstehen sein [...]
$* 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!
Re: Verständnisproblem beim Quoting
@meillo
Das waren jetzt interessante Beispiele.... schau Dir mal das Ergebnis in meiner Buster-Bash an:
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 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!
Re: Verständnisproblem beim Quoting
Das kommt von der History-Expansion der Bash. (Ich verwende eine mksh, die macht sowas nicht.)TomL hat geschrieben:28.02.2020 21:25:12Das 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?Code: Alles auswählen
$ echo "Er sagte: "Halt!"" bash: !"": event not found
Du musst die Ausrufezeichen bzw. die Ersetzung halt quoten.
Use ed once in a while!
Re: Verständnisproblem beim Quoting
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.
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.
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
Re: Verständnisproblem beim Quoting
! 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...
Kurz in einem Shellscript wird es eventuell tun...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.
rot: Moderator wanne spricht, default: User wanne spricht.
Re: Verständnisproblem beim Quoting
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? 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.
Re: Verständnisproblem beim Quoting
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.)TomL hat geschrieben:29.02.2020 10:49:50Code: Alles auswählen
# echo "$(iw dev $dev scan | grep -i "ssid: $ssid")" SSID: Fritz!Box 6490 Cable
Dieser Befehl entspricht meinem meinem ``Sofort Anhalten!''-Beispiel. Echo bekommt zwei Argumente:Code: Alles auswählen
# echo "iw dev $dev scan | grep -i "ssid: $ssid"" iw dev wlxec086b1e82ae scan | grep -i ssid: Fritz!Box 6490 Cable
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!
Re: Verständnisproblem beim Quoting
@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')
(Ich habe kein `iw', darum mit echo.)
In meiner Bash ebenso:
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:
Ich erklaere gerne noch mehr, wenn du mir nochmal zeigst, wo genau die Verstaendnisprobleme und Unklarheiten noch liegen.
Ja.TomL hat geschrieben:29.02.2020 12:00:29Insbesondere 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".
Warum denn nicht? Schau dir nochmal mein Beispiel mit den Ebenen an. (Tipp: $() oeffet eine neue Ebene.)Aber dieses Konstrukt hat die offene Frage, weil " "" " eben nicht den Klammerregeln von innen nach außen folgen.
Weniger Quoting heisst nicht, dass es korrekter ist.Die zweite Variante sieht syntaktisch hinsichtlich des Quotings sauber aus,
Funktioniert sie zufaellig oder weil sie korrekt ist?sie funktioniert auch,
Darum funktioniert sie bei mir auch nicht:aber sie erfüllt nicht die Bedingung, den Rückgabetext als gesamtes zu quoten.
Code: Alles auswählen
$ if [ -z $(echo "ssid: Fritz!Box") ]; then echo true; fi
mksh: [: Fritz!Box: unexpected operator/operand
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
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.
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:Welches Statement übenehme ich dauerhauft? 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.
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!
Re: Verständnisproblem beim Quoting
Das Problem ist zudem auch abhängig von der Deklaration resp. der Zuweisung des Wertes... schau Dir das mal an:
Dieses Beispiel von Dir...
... was ich so darstellen würde, ...
.... 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.
*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:
Wenn das zutreffen würde, also basierend auf der Behandlung durch $(...), käme ich damit als Erklärung bestens zurecht....
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
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:funktioniert sie zufaellig oder weil sie korrekt ist?
Code: Alles auswählen
if [ -z "$(iw dev $dev scan | grep -i "ssid: $ssid")" ]; then
+-----------------------------+ +-+
Code: Alles auswählen
if ; then ...
[ -z " " ]
$( )
iwvdrv " " scan |
$dev
grep -i " "
ssid: $ssid
Code: Alles auswählen
if [ -z "$(iw dev "$dev" scan | grep -i "ssid: $ssid")" ]; then
+----+ +-----------+
+---------------------------------------------+
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"
+----+ +-----------+
+---------------------------------------------+
Re: Verständnisproblem beim Quoting
Die kurze Antwort:
Hier trotzdem noch ein paar Anmerkungen zum Rest deines Posts.
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:
Da gibt es die nette Frage, wie man diese Zeichenfolge ausgibt: "'"
Einerseits geht das natuerlich mit Backslashes, aber es geht auch ohne:
(Man muss das ``nur'' stupide abarbeiten, dann ist es einfach.)
Tada! Jetzt hast du's geschnallt.TomL hat geschrieben:29.02.2020 14:14:28Nachtrag:
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:Wenn das zutreffen würde, also basierend auf der Behandlung durch $(...), käme ich damit als Erklärung bestens zurecht....Code: Alles auswählen
if [ -z "$( )" ]; then iw dev "$dev" scan | grep -i "ssid: $ssid" +----+ +-----------+ +---------------------------------------------+
Hier trotzdem noch ein paar Anmerkungen zum Rest deines Posts.
Immer wenn ein Ausrufezeichen ungequotet oder nur in Double-Quotes da steht, greift die History-Expansion ein. Das betrifft die letzten beiden Faelle.TomL hat geschrieben:29.02.2020 14:14:28Das 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
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
Einerseits geht das natuerlich mit Backslashes, aber es geht auch ohne:
Code: Alles auswählen
B-) echo \"\'\"
"'"
B-) echo '"'"'"'"'
"'"
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.)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.
Use ed once in a while!
Re: Verständnisproblem beim Quoting
Jau, und ich Danke Dir für die Hilfe.
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.
Re: [gelöst] Verständnisproblem beim Quoting
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!
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!