Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.comp.os.unix.shell > #14537 > unrolled thread

richtig quoten

Started byAlexander Goetzenstein <alexander_goetzenstein@web.de>
First post2025-07-16 15:14 +0200
Last post2025-07-16 23:38 +0200
Articles 11 — 5 participants

Back to article view | Back to de.comp.os.unix.shell


Contents

  richtig quoten Alexander Goetzenstein <alexander_goetzenstein@web.de> - 2025-07-16 15:14 +0200
    Re: richtig quoten Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2025-07-16 13:22 +0000
      Re: richtig quoten Ulli Horlacher <framstag@rus.uni-stuttgart.de> - 2025-07-16 16:19 +0000
    Re: richtig quoten "Peter J. Holzer" <hjp-usenet4@hjp.at> - 2025-07-16 16:06 +0200
      Re: richtig quoten "Peter J. Holzer" <hjp-usenet4@hjp.at> - 2025-07-16 17:30 +0200
    Re: richtig quoten Stefan Reuther <stefan.news@arcor.de> - 2025-07-16 18:05 +0200
      Re: richtig quoten Alexander Goetzenstein <alexander_goetzenstein@web.de> - 2025-07-16 21:17 +0200
      Re: richtig quoten Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-07-16 23:59 +0200
        Re: richtig quoten Stefan Reuther <stefan.news@arcor.de> - 2025-07-17 18:27 +0200
          Re: richtig quoten Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-07-17 22:20 +0200
    Re: richtig quoten Helmut Waitzmann <nn.throttle@xoxy.net> - 2025-07-16 23:38 +0200

#14537 — richtig quoten

FromAlexander Goetzenstein <alexander_goetzenstein@web.de>
Date2025-07-16 15:14 +0200
Subjectrichtig quoten
Message-ID<078ee6a7-4eb6-4927-a40f-49bb333298b3@alexander-goetzenstein.my-fqdn.de>
Hallo,
ich habe mir angewöhnt, zur leichteren Fehlersuche und
Tippfehlervermeidung Befehle in Scripts zuerst in eine Variable zu
stecken und diese dann mittels eval auszuführen. Meist gibt es kein
Problem, aber momentan stehe ich auf dem Schlauch. Folgender Befehl will
nicht so wie ich es will:

> [...]
> ## Beispielwerte:
> DATUM=2025-07-16_14-10
> FERTIG=2025-07-16_14-15
> LAUFZEIT=5 Minuten
> [...]
> kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &


Letzteren Befehl möchte ich wie erwähnt behandeln, doch Konstrukte wie

> BEFEHL=kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
> eval "$BEFEHL"

ergeben nicht das gewünschte Ergebnis. Meist habe ich nur eine Ausgabe wie

> Beginn: 

erreicht, alles andere ist abgeschnitten, wenn nicht gleich eine
Fehlermeldung statt des Popups kam. Jetzt habe ich soviel mit ' und "
herumgewurschtelt, dass ich den Plan verloren hab. Wie geht es richtig?



-- 
Gruß
Alex

[toc] | [next] | [standalone]


#14538

FromUlli Horlacher <framstag@rus.uni-stuttgart.de>
Date2025-07-16 13:22 +0000
Message-ID<1058934$r7p$1@rusnews.informatik.uni-stuttgart.de>
In reply to#14537
Alexander Goetzenstein <alexander_goetzenstein@web.de> wrote:
> Hallo,
> ich habe mir angewöhnt, zur leichteren Fehlersuche und
> Tippfehlervermeidung Befehle in Scripts zuerst in eine Variable zu
> stecken und diese dann mittels eval auszuführen. Meist gibt es kein
> Problem, aber momentan stehe ich auf dem Schlauch. Folgender Befehl will
> nicht so wie ich es will:
> 
>> [...]
>> ## Beispielwerte:
>> DATUM=2025-07-16_14-10
>> FERTIG=2025-07-16_14-15
>> LAUFZEIT=5 Minuten

Das funktioniert so nicht. Da fehlen Quote-Zeichen!
Letzteres macht folgendes:
Es ruft den externen Befehl Minuten auf mit der Environment Variablen
LAUFZEIT=5



>> kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
> 
> 
> Letzteren Befehl möchte ich wie erwähnt behandeln, doch Konstrukte wie
> 
>> BEFEHL=kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>> eval "$BEFEHL"
> 
> ergeben nicht das gewünschte Ergebnis. 

Das wird mit dem & nur noch schlimmer!


> Wie geht es richtig?

Gar nicht.
eval und Quotes beissen sich. Don't do that.


-- 
Ullrich Horlacher              Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart         E-Mail: horlacher@tik.uni-stuttgart.de
Allmandring 30a                Tel:    ++49-711-68565868
70569 Stuttgart (Germany)      WWW:    https://www.tik.uni-stuttgart.de/

[toc] | [prev] | [next] | [standalone]


#14544

FromUlli Horlacher <framstag@rus.uni-stuttgart.de>
Date2025-07-16 16:19 +0000
Message-ID<1058je5$tds$1@rusnews.informatik.uni-stuttgart.de>
In reply to#14538
Ulli Horlacher <framstag@rus.uni-stuttgart.de> wrote:

>> ich habe mir angewöhnt, zur leichteren Fehlersuche und
>> Tippfehlervermeidung Befehle in Scripts zuerst in eine Variable zu
>> stecken und diese dann mittels eval auszuführen. Meist gibt es kein
>> Problem, aber momentan stehe ich auf dem Schlauch. Folgender Befehl will
>> nicht so wie ich es will:
>> 
>>> [...]
>>> ## Beispielwerte:
>>> DATUM=2025-07-16_14-10
>>> FERTIG=2025-07-16_14-15
>>> LAUFZEIT=5 Minuten
(...)
>> Wie geht es richtig?
> 
> Gar nicht.
> eval und Quotes beissen sich. Don't do that.

Nicht ganz das, was du gefragt hast, aber vielleicht hilft dir das:
Ich hab vdo (verbode do) geschrieben, das anzeigt, welches Kommando es
ausfuehrt UND das die Argument korrekt uebergibt.
Mit der environment variable VDO=n werden Kommandos nur angezeigt, aber
nicht ausgefuehrt.
Mit der environment variable VDO=i wird vorher gefragt ob die Kommandos
ausgefuehrt werden sollen.

framstag@watschel:/moep: vdo -h
vdo: verbose do (with quoting)
usage: vdo [-i] [-n] [-s SECONDS] COMMAND [ARG...]
options: -i  prompt before execution
         -n  dry-run mode, no execution
         -s  wait SECONDS before execution
env var: VDO=i VDO=n

Ich hab dein Beispiel etwas umgewandelt in:

framstag@moep:/tmp: cat beispiel.sh 

DATUM="2025-07-16_14-10"
FERTIG="2025-07-16_14-15"
LAUFZEIT="5 Minuten"
vdo showargs kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT"


showargs ist ein weiteres Programm von mir, das nur anzeigt welche Argumente
uebergeben werden. Sonst sieht man Shell Metazeichen wie Spaces nicht.


framstag@moep:/tmp: ./beispiel.sh 

$ showargs kdialog --msgbox 'Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten'
kdialog --msgbox Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten
  1 [kdialog]
  2 [--msgbox]
  3 [Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten]

framstag@moep:/tmp: VDO=n ./beispiel.sh

$ showargs kdialog --msgbox 'Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten'


framstag@moep:/tmp: VDO=i ./beispiel.sh

$ showargs kdialog --msgbox 'Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten'
execute? [y]
kdialog --msgbox Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten
  1 [kdialog]
  2 [--msgbox]
  3 [Beginn:  2025-07-16_14-10 \nEnde:     2025-07-16_14-15 \n5 Minuten]


vdo und showargs findest du da: https://fex.belwue.de/fstools/

-- 
Ullrich Horlacher              Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart         E-Mail: horlacher@tik.uni-stuttgart.de
Allmandring 30a                Tel:    ++49-711-68565868
70569 Stuttgart (Germany)      WWW:    https://www.tik.uni-stuttgart.de/

[toc] | [prev] | [next] | [standalone]


#14539

From"Peter J. Holzer" <hjp-usenet4@hjp.at>
Date2025-07-16 16:06 +0200
Message-ID<slrn107fcfp.n7bl.hjp-usenet4@trintignant.hjp.at>
In reply to#14537
On 2025-07-16 15:14, Alexander Goetzenstein <alexander_goetzenstein@web.de> wrote:
> ich habe mir angewöhnt, zur leichteren Fehlersuche und
> Tippfehlervermeidung Befehle in Scripts zuerst in eine Variable zu
> stecken und diese dann mittels eval auszuführen.

Zusätzlich zu dem was Ulli schon geschrieben hat:

Das klingt nach einer ganz schlechten Idee. Code und Daten sollte man
möglichst trennen und eval nur verwenden, wenn es nicht anders geht (was
in der Shell leider häufiger der Fall ist als in vernünftigen
Programmiersprachen).

        hjp

[toc] | [prev] | [next] | [standalone]


#14541

From"Peter J. Holzer" <hjp-usenet4@hjp.at>
Date2025-07-16 17:30 +0200
Message-ID<slrn107fhda.p4mv.hjp-usenet4@trintignant.hjp.at>
In reply to#14539
On 2025-07-16 16:46, Stefan Ram <ram@zedat.fu-berlin.de> wrote:
> "Peter J. Holzer" <hjp-usenet4@hjp.at> schrieb oder zitierte:
>>Das klingt nach einer ganz schlechten Idee. Code und Daten sollte man
>>möglichst trennen und eval nur verwenden, wenn es nicht anders geht
>
>   Nehmen wir einmal dieses Beispiel:
>
>|#!/usr/bin/env bash
>|set -euo pipefail
>|backup_dir="${1:-$HOME}"
>|timestamp=$(date +%Y-%m-%d_%H-%M-%S)
>|tar -czf "$HOME/backup_$timestamp.tar.gz" -C "$backup_dir" .
>
>   . "backup_dir" und "timestamp" sind "Daten", und die letzte Zeile
>   ist "Code". Aber sie enthält mit den Argumenten auch Daten.

Jedes (nicht-triviale) Programm enthält "Daten": Variable, Literale,
etc.

Aber das ist (vielleicht nicht für den Computer, aber für den Menschen)
etwas anderes als Code dynamisch zu erzeugen und auszuführen. Das macht
es einfach sehr viel schwieriger, nachzuvollziehen, was das Programm
eigentlich tut. Und da Alexanders Ziel nach seiner eigenen Aussage
"leichtere Fehlersuche" ist, schießt er sich damit selbst ins Knie.
Ganz besonders in der Shell, deren Parse-Mechanismus ja für sich schon
einige Footguns bereithält. Wenn er das in Lisp macht - ok, mag dort
normal sein. In Python? "There must be a better way!"[1], aber
beherrschbar. In der Shell? You're in for a world of pain.

        hjp

[1] Channeling Raymond Hettinger.

[toc] | [prev] | [next] | [standalone]


#14543

FromStefan Reuther <stefan.news@arcor.de>
Date2025-07-16 18:05 +0200
Message-ID<1058pld.3mk.1@stefan.msgid.phost.de>
In reply to#14537
Am 16.07.2025 um 15:14 schrieb Alexander Goetzenstein:
>> [...]
>> ## Beispielwerte:
>> DATUM=2025-07-16_14-10
>> FERTIG=2025-07-16_14-15
>> LAUFZEIT=5 Minuten
>> [...]
>> kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
> 
> Letzteren Befehl möchte ich wie erwähnt behandeln, doch Konstrukte wie
> 
>> BEFEHL=kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>> eval "$BEFEHL"

Allen Unkenrufen zum Trotz ist das ziemlich einfach.

Du musst dafür sorgen, dass die Variable BEFEHL genau den Befehl mit
allen gewünschten Sonderzeichen enthält. Das geht am einfachsten, indem
du vor alle Sonderzeichen einen Backslash packst:

    BEFEHL="kdialog --msgbox \"Beginn:  \$DATUM \\nEnde:     \$FERTIG\\n\$LAUFZEIT\" &"

Im konkreten Fall reicht auch, einfach ein Hochkomma davor und eins dahinter

    BEFEHL='kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG\n$LAUFZEIT" &'

aber das wird dann unhandlich, wenn der Befehl Hochkommate enthält.

Zum Prüfen: echo "$BEFEHL" - da muss genau der Befehl zurückkommen,
immer noch mit den $VARIABLEN und allen Sonderzeichen.

Dennoch wäre meine Empfehlung, eine Shellfunktion zu verwenden.

    status() {
       kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
    }
    BEFEHL=status

Dann kannst du zum Aufrufen auch auf das 'eval' verzichten, sondern
einfach $BEFEHL aufrufen.


  Stefan

[toc] | [prev] | [next] | [standalone]


#14545

FromAlexander Goetzenstein <alexander_goetzenstein@web.de>
Date2025-07-16 21:17 +0200
Message-ID<591d43a4-5fc3-4cfe-be66-274905c3c431@alexander-goetzenstein.my-fqdn.de>
In reply to#14543
Hallo,

Am 16.07.25 um 18:05 schrieb Stefan Reuther:
> Du musst dafür sorgen, dass die Variable BEFEHL genau den Befehl mit
> allen gewünschten Sonderzeichen enthält. Das geht am einfachsten, indem
> du vor alle Sonderzeichen einen Backslash packst:

Danke, danach habe ich gesucht.


-- 
Gruß
Alex

[toc] | [prev] | [next] | [standalone]


#14547

FromHelmut Waitzmann <nn.throttle@xoxy.net>
Date2025-07-16 23:59 +0200
Message-ID<83jz47sso6.fsf@helmutwaitzmann.news.arcor.de>
In reply to#14543
 Stefan Reuther <stefan.news@arcor.de>:
> Am 16.07.2025 um 15:14 schrieb Alexander Goetzenstein:
>>> [...]
>>> ## Beispielwerte:
>>> DATUM=2025-07-16_14-10
>>> FERTIG=2025-07-16_14-15
>>> LAUFZEIT=5 Minuten
>>> [...]
>>> kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>>
>> Letzteren Befehl möchte ich wie erwähnt behandeln, doch 
>> Konstrukte wie 
>>
>>
>>> BEFEHL=kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>>> eval "$BEFEHL"
>
> Allen Unkenrufen zum Trotz ist das ziemlich einfach. 
>
>
> Du musst dafür sorgen, dass die Variable BEFEHL genau den Befehl 
> mit allen gewünschten Sonderzeichen enthält. Das geht am 
> einfachsten, indem du vor alle Sonderzeichen einen Backslash 
> packst: 
>
>
>     BEFEHL="kdialog --msgbox \"Beginn:  \$DATUM \\nEnde:     \$FERTIG\\n\$LAUFZEIT\" &"


 Wenn in dem Befehl ein Newline‐Zeichen vorkommt, scheitert das, 
 weil Newline‐Zeichen mit einem Backslash nicht geschützt werden 
 können.  (Statt dessen werden sie mitsamt dem Backslash entfernt, 
 so, als stünden sie nicht da.  Im konkreten Beispiel kommen aber 
 keine Newline‐Zeichen vor.) 


>
> Im konkreten Fall reicht auch, einfach ein Hochkomma davor und 
> eins dahinter 
>
>
>     BEFEHL='kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG\n$LAUFZEIT" &'
>
> aber das wird dann unhandlich, wenn der Befehl Hochkommate enthält. 
>

 Dann ersetzt man einfach zuvor alle im Befehl stehenden 
 Hochkommata (mit einem Suchen‐und‐Ersetzen‐Kommando des 
 Texteditors) durch die Zeichenfolge „'\''“ (ein Hochkomma, einen 
 umgekehrten Schrägstrich und zwei Hochkommata). 


> Zum Prüfen: echo "$BEFEHL" - da muss genau der Befehl zurückkommen, 
> immer noch mit den $VARIABLEN und allen Sonderzeichen. 
>

 „echo“ gibt den Text unter Umständen nicht unverändert 
 wieder.  „printf“ ist besser: 


   printf '%s\n' "$BEFEHL"


> Dennoch wäre meine Empfehlung, eine Shellfunktion zu verwenden. 
>
>
>     status() {
>        kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>     }
>     BEFEHL=status
>
> Dann kannst du zum Aufrufen auch auf das 'eval' verzichten, sondern 
> einfach $BEFEHL aufrufen. 
>

 Nicht 


   $BEFEHL


 sondern 


   "$BEFEHL".


 Grundregel:  Variablenexpansionen setzt man immer in 
 Anführungszeichen, es sei denn, man will komische Effekte mit in 
 der Variablen „IFS“ aufgezählten Sollbruchstellen haben. 

[toc] | [prev] | [next] | [standalone]


#14548

FromStefan Reuther <stefan.news@arcor.de>
Date2025-07-17 18:27 +0200
Message-ID<105bfab.29g.1@stefan.msgid.phost.de>
In reply to#14547
Am 16.07.2025 um 23:59 schrieb Helmut Waitzmann:
> Stefan Reuther <stefan.news@arcor.de>:
>> Du musst dafür sorgen, dass die Variable BEFEHL genau den Befehl mit
>> allen gewünschten Sonderzeichen enthält. Das geht am einfachsten,
>> indem du vor alle Sonderzeichen einen Backslash packst:
>>
>>     BEFEHL="kdialog --msgbox \"Beginn:  \$DATUM \\nEnde:    
>> \$FERTIG\\n\$LAUFZEIT\" &"
> 
> Wenn in dem Befehl ein Newline‐Zeichen vorkommt, scheitert das, weil
> Newline‐Zeichen mit einem Backslash nicht geschützt werden können. 

Die Newlines muss man hier nicht gesondert behandeln, sondern einfach
stehenlassen:

      BEFEHL="echo \"foo
      bar\""

      eval "$BEFEHL"


>> Im konkreten Fall reicht auch, einfach ein Hochkomma davor und eins
>> dahinter
>>
>>     BEFEHL='kdialog --msgbox "Beginn:  $DATUM \nEnde:    
>> $FERTIG\n$LAUFZEIT" &'
>>
>> aber das wird dann unhandlich, wenn der Befehl Hochkommate enthält.
> 
> Dann ersetzt man einfach zuvor alle im Befehl stehenden Hochkommata (mit
> einem Suchen‐und‐Ersetzen‐Kommando des Texteditors) durch die
> Zeichenfolge „'\''“ (ein Hochkomma, einen umgekehrten Schrägstrich und
> zwei Hochkommata).

Das ist das, was ich mit unhandlich meine.

>> Dennoch wäre meine Empfehlung, eine Shellfunktion zu verwenden.
>>
>>     status() {
>>        kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG
>> \n$LAUFZEIT" &
>>     }
>>     BEFEHL=status
>>
>> Dann kannst du zum Aufrufen auch auf das 'eval' verzichten, sondern
>> einfach $BEFEHL aufrufen.
> 
> Nicht
> 
>   $BEFEHL
> 
> sondern
> 
>   "$BEFEHL".

Das kommt halt drauf an, was man will.

"$BEFEHL" -- die Variable enthält ein Wort, das als Befehlsname
interpretiert werden soll, z.B. einen Dateinamen, der Leerzeichen
enthalten kann.

$BEFEHL -- die Variable enthält ein Kommando mit Optionen. Das ist
angemessen für Dinge wie "CC=gcc -m32 -sysroot=/whatever", aber
Parameter mit Leerzeichen drin sind nicht möglich.

eval "$BEFEHL" -- die Variable enthält ein Kommando, das
Shell-Sonderzeichen beinhalten kann, von Quoting über weitere Variablen
bis zu '&' und Umleitungen.

Und außer Konkurrenz: '$BEFEHL' -- jemand war der Meinung, dass der Name
des Binaries mit einem Dollarzeichen beginnen solle.


Shell ist nicht so eine unvorhersehbare Naturkatastrophe, wie sie
manchmal dargestellt wird, aber man muss eben immer gut bei der Sache
sein und sich zu jedem Zeitpunkt klar sein, was für Werte man wie in
seine Variablen packt, und wenn man zu viel auf einmal will, wird es
unübersichtlich.

Wenn eine Variable aber z.B. entweder den Wert 'true' oder den Wert
'false' beinhalten kann, kann man Dinge wie 'if $var; then' ganz elegant
aufschreiben, ohne den Code mit Quoting zu verunstalten.


  Stefan

[toc] | [prev] | [next] | [standalone]


#14549

FromHelmut Waitzmann <nn.throttle@xoxy.net>
Date2025-07-17 22:20 +0200
Message-ID<8334auy3fq.fsf@helmutwaitzmann.news.arcor.de>
In reply to#14548
 Stefan Reuther <stefan.news@arcor.de>:
> Am 16.07.2025 um 23:59 schrieb Helmut Waitzmann:
>> Stefan Reuther <stefan.news@arcor.de>:
>>> Du musst dafür sorgen, dass die Variable BEFEHL genau den 
>>> Befehl mit allen gewünschten Sonderzeichen enthält. Das geht 
>>> am einfachsten, indem du vor alle Sonderzeichen einen 
>>> Backslash packst: 
>>>
>>>
>>>     BEFEHL="kdialog --msgbox \"Beginn:  \$DATUM \\nEnde:    
>>> \$FERTIG\\n\$LAUFZEIT\" &"
>>
>> Wenn in dem Befehl ein Newline‐Zeichen vorkommt, scheitert das, 
>> weil Newline‐Zeichen mit einem Backslash nicht geschützt werden 
>> können. 
>>
>
> Die Newlines muss man hier nicht gesondert behandeln, sondern 
> einfach stehenlassen: 
>
>
>       BEFEHL="echo \"foo
>       bar\""
>
>       eval "$BEFEHL"
>

 Das ist richtig, entspricht aber nicht dem, was du oben 
 als Regel beschrieben hast (nochmal zitiert): 


>>> Du musst dafür sorgen, dass die Variable BEFEHL genau den 
>>> Befehl mit allen gewünschten Sonderzeichen enthält. Das geht 
>>> am einfachsten, indem du vor alle Sonderzeichen einen 
>>> Backslash packst: 
>>>


 Du hast mehr als diese Regel angewendet:  Du hast außerdem die 
 ganze Kommandozeile in Anführungszeichen gesetzt. 


 Außerdem hat man dann noch die Frage zu beantworten, welche 
 Zeichen denn Sonderzeichen sind.  (Und die Antwort fällt 
 unterschiedlich aus je nachdem, ob man die ganze Kommandozeile in 
 Anführungszeichen setzen will oder nicht.) 


 Wie du richtig bemerkt hast, ist das Newline‐Zeichen in diesem 
 Fall kein Sonderzeichen. 

>
>>> Im konkreten Fall reicht auch, einfach ein Hochkomma davor und 
>>> eins dahinter 
>>>
>>>
>>>     BEFEHL='kdialog --msgbox "Beginn:  $DATUM \nEnde:    
>>> $FERTIG\n$LAUFZEIT" &'
>>>
>>> aber das wird dann unhandlich, wenn der Befehl Hochkommate 
>>> enthält. 
>>>
>>
>> Dann ersetzt man einfach zuvor alle im Befehl stehenden 
>> Hochkommata (mit einem Suchen‐und‐Ersetzen‐Kommando des 
>> Texteditors) durch die Zeichenfolge „'\''“ (ein Hochkomma, 
>> einen umgekehrten Schrägstrich und zwei Hochkommata). 
>>
>
> Das ist das, was ich mit unhandlich meine. 
>

 Da gehen vielleicht unsere Vorlieben auseinander:  Ich möchte 
 lieber die ganze Kommandozeile im Texteditor markieren und dann 
 stupide bei der ersten Stelle, die der Editor auf dem markierten 
 Textausschnitt findet, die Rückfrage „Ersetzen: [J]a, [N]ein, [A]lle?“ 
 mit „A“ beantworten und habe genau alle Änderungen auf einen 
 Sitz vorgenommen.  Dabei muss ich nicht entscheiden, welche 
 Zeichen denn nun Sonderzeichen sind und welche nicht. 


>>> Dennoch wäre meine Empfehlung, eine Shellfunktion zu 
>>> verwenden. 
>>>
>>>
>>>     status() {
>>>        kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG
>>> \n$LAUFZEIT" &
>>>     }
>>>     BEFEHL=status
>>>
>>> Dann kannst du zum Aufrufen auch auf das 'eval' verzichten, 
>>> sondern einfach $BEFEHL aufrufen. 
>>>
>>
>> Nicht 
>>
>>
>>   $BEFEHL
>>
>> sondern 
>>
>>
>>   "$BEFEHL".
>
> Das kommt halt drauf an, was man will. 
>

 Genau.  Ich wiederhole es gerne:  Wenn man will, dass die in der 
 Shell‐Variablen „IFS“ genannten Zeichen als Sollbruchstellen 
 wirken, dann muss man die Anführungszeichen weglassen; wenn man 
 das nicht will, muss man sie hinschreiben. 


> "$BEFEHL" -- die Variable enthält ein Wort, das als Befehlsname 
> interpretiert werden soll, z.B. einen Dateinamen, der Leerzeichen 
> enthalten kann. 
>

 Und genau da ist die Falle: nicht „Leerzeichen enthalten kann“ 
 sondern „IFS‐Zeichen enthalten kann“. 


>
> $BEFEHL -- die Variable enthält ein Kommando mit Optionen. Das ist 
> angemessen für Dinge wie "CC=gcc -m32 -sysroot=/whatever", aber 
> Parameter mit Leerzeichen drin sind nicht möglich. 
>

 … mit IFS‐Zeichen drin 


>
> eval "$BEFEHL" -- die Variable enthält ein Kommando, das 
> Shell-Sonderzeichen beinhalten kann, von Quoting über weitere 
> Variablen bis zu '&' und Umleitungen. 


 Kurz:  Die Variable enthält eine Kommandozeile.  (Darin können 
 auch mehrere Kommandos sein.) 


>
> Shell ist nicht so eine unvorhersehbare Naturkatastrophe, wie 
> sie manchmal dargestellt wird, aber man muss eben immer gut bei 
> der Sache sein und sich zu jedem Zeitpunkt klar sein, was für 
> Werte man wie in seine Variablen packt, und wenn man zu viel auf 
> einmal will, wird es unübersichtlich. 
>

 Da sind wir uns vollkommen einig. 

[toc] | [prev] | [next] | [standalone]


#14546

FromHelmut Waitzmann <nn.throttle@xoxy.net>
Date2025-07-16 23:38 +0200
Message-ID<83o6tjstnf.fsf@helmutwaitzmann.news.arcor.de>
In reply to#14537
 Alexander Goetzenstein <alexander_goetzenstein@web.de>:
> Hallo,
> ich habe mir angewöhnt, zur leichteren Fehlersuche und 
> Tippfehlervermeidung Befehle in Scripts zuerst in eine Variable 
> zu stecken und diese dann mittels eval auszuführen. Meist gibt 
> es kein Problem, aber momentan stehe ich auf dem Schlauch. 
> Folgender Befehl will nicht so wie ich es will: 
>
>
>> [...]
>> ## Beispielwerte:
>> DATUM=2025-07-16_14-10
>> FERTIG=2025-07-16_14-15
>> LAUFZEIT=5 Minuten
>> [...]
>> kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>


 Erhältst du damit das gewünschte?  (Ich kenne „kdialog“ nicht, 
 deshalb frage ich und gehe im folgenden davon aus, dass das der 
 Fall ist.) 


>
> Letzteren Befehl möchte ich wie erwähnt behandeln, doch 
> Konstrukte wie
>
>> BEFEHL=kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT" &
>> eval "$BEFEHL"
>
> ergeben nicht das gewünschte Ergebnis. 
>

 […]

> Wie geht es richtig? 
>

 Eine Kommandozeile, die ein simple command darstellt, kannst du 
 auf folgende Weise so umarbeiten, dass sie in eine Shell‐Variable 
 (hier: „BEFEHL“) gesteckt werden und anschließend per 


   eval "$BEFEHL"


 aufgerufen werden kann: 


 Als ersten Schritt schreib die Kommandozeile zunächst ohne 
 „BEFEHL=“ am Zeilenanfang hin. 


 Im Beispiel sieht es so aus: 


   kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT"


 Als zweiten Schritt nimm in deinem Texteditor das 
 Suche‐und‐Ersetze‐Kommando her und ersetze alle in der 
 Kommandozeile vorkommenden Apostrophe („'“) durch die folgende 
 Zeichenfolge: „'\''“ (einen Apostroph, einen Backslash und zwei 
 Apostrophe). 


 Im Beispiel sieht es so aus: 


   kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT"


 (Das ist hier unverändert, weil in der Kommandozeile keine 
 Apostrophe vorkommen.) 


 Als dritten Schritt setze vorne und hinten an die Kommandozeile 
 jeweils einen Apostroph. 


 Im Beispiel sieht es so aus: 


   'kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT"'


 Als vierten Schritt setze vor den Apostroph am 
 Kommandozeilenanfang noch den Text „BEFEHL=“. 


 Im Beispiel sieht es so aus: 


   BEFEHL='kdialog --msgbox "Beginn:  $DATUM \nEnde:     $FERTIG \n$LAUFZEIT"'



 Jetzt hast du ein Zuweisekommando, das an die Variable „BEFEHL“ 
 die Kommandozeile in einer Form zuweist, die es erlaubt, die 
 Kommandozeile mittels des Befehls 


   eval "$BEFEHL"


 auszuführen. 


 Diese Methode funktioniert immer, egal, welche Sonderzeichen das 
 simple command in der Kommandozeile enthält. 


 Zum Hintergrund, warum das funktioniert:  Hast du noch Zugriff 
 auf den im folgenden genannten Usenet‐Beitrag?  (Falls gewünscht, 
 kann ich ihn auch nochmal posten.) 


   Subject: Sonderzeichen in der Shell-Kommandozeile?  Quoting hilft! (was: rekursive Suche)
   From: Helmut Waitzmann <nn.throttle@xoxy.net>
   Newsgroups: de.comp.os.unix.linux.misc, de.comp.os.unix.shell
   Followup-To: de.comp.os.unix.shell
   Date: Sat, 04 Jan 2025 23:03:33 +0100
   Message-ID: <83o70muthm.fsf_-_@helmutwaitzmann.news.arcor.de>

[toc] | [prev] | [standalone]


Back to top | Article view | de.comp.os.unix.shell


csiph-web