
Hallo AN ALLE und Danke im Voraus.
Ich habe im Forum nach meiner Situation gesucht und konnte keine Lösung finden. Ich habe ein Skript, an das ich in der Befehlszeile Argumente/Optionen/Parameter übergebe. Einer der Werte enthält ein Leerzeichen, das ich in Anführungszeichen gesetzt habe. Es wäre vielleicht einfacher, ein Beispiel anzugeben. Verzeihen Sie meine Verwendung von Argumenten/Optionen/Parametern.
$: ./test1.ksh -n -b -d "Home Videos"
Mein Problem besteht darin, eine Variable auf „Home Videos“ zu setzen und sie zusammen zu verwenden. In meinem Beispiel dient -d zur Angabe eines Verzeichnisses. Nicht alle Verzeichnisse haben Leerzeichen, in meinem Fall jedoch einige.
Dies ist ein Beispiel für den Code, der nicht wie erwartet funktioniert.
#!/bin/ksh
Function1()
{
echo "Number of Args in Function1: $#"
echo "Function1 Args: $@"
SetArgs $*
}
SetArgs()
{
echo -e "\nNumber of Args in SetArgs: $#"
echo "SetArgs Args: $@"
while [ $# -gt 0 ]
do
case $1 in
-[dD])
shift
export DirectoryName=$1
;;
-[nN])
export Var1=No
shift
;;
-[bB])
export Var2=Backup
shift
;;
*)
shift
;;
esac
done
Function2
}
Function2()
{
echo "Directory Name: ${DirectoryName}"
}
Function1 $*
Wenn ich dies ausführe, erhalte ich für den Verzeichnisnamen nur „Home“ statt „Home Videos“. Siehe unten.
$ ./test1.ksh -n -b -d "Home Videos"
Number of Args in Function1: 5
Function1 Args: -n -b -d Home Videos
Number of Args in SetArgs: 5
SetArgs Args: -n -b -d Home Videos
Var1 is set to: No
Var2 is set to: Backup
Directory Name: Home
Was ich erwarte und bisher nicht erreichen konnte, ist:
$ ./test1.ksh -n -b -d "Home Videos"
Number of Args in Function1: 4
Function1 Args: -n -b -d "Home Videos"
Number of Args in SetArgs: 4
SetArgs Args: -n -b -d "Home Videos"
Var1 is set to: No
Var2 is set to: Backup
Directory Name: Home Videos <-- Without double quotes in the final usage.
Ich bin für jede Hilfe, die ich hierzu bekommen kann, sehr dankbar ... Ich habe versucht, die Anführungszeichen zu vermeiden, aber ohne Erfolg.
Vielen Dank für die Zeit und Mühe, die Sie mir beim Herausfinden dieser Sache gewidmet haben.
Grüße, Daniel
Antwort1
Mit $*
oder $@
ohne Anführungszeichenniemalsmacht Sinn.
"$*"
ist die Verkettung der Positionsparameter mit dem ersten Zeichen (oder Byte, je nach Shell) von $IFS
, "$@"
ist die Liste der Positionsparameter.
Ohne Anführungszeichen ist es dasselbe, unterliegt aber Split+Glob (oder nur der Entfernung leerer Elemente mit zsh
), wie jede andere Parametererweiterung ohne Anführungszeichen (einige Shells trennen Argumente in $*
auch, selbst wenn $IFS
es leer ist).
Hier möchten Sie die Liste der Argumente übergebenwie es istzu Ihrer Funktion, also lautet es:
SetArgs "$@"
[...]
Function1 "$@"
Beachten Sie, dass bei ksh88 $IFS
das Leerzeichen enthalten sein muss (was standardmäßig der Fall ist), damit es ordnungsgemäß funktioniert (ein von der Bourne-Shell übernommener Fehler, behoben in ksh93).
Beachten Sie auch, dass bei einigen Implementierungen von ksh
(wie älteren Versionen von zsh
in ksh
der Emulation)
export DirectoryName=$1
ist ein Split+Glob-Aufruffall. export
ist einer dieser Befehle in Korn-ähnlichen Shells, die Shell-Code auswerten könnendurch arithmetische Auswertung in Array-Indizes), so ist eseiner der Fälle, in denen es wichtig ist, Variablen in Anführungszeichen zu setzen, um die Einführung von Schwachstellen bei der Befehlsinjektion zu vermeiden.
Beispiel:
$ (exec -a ksh zsh-4.0.1 -c 'export x=$a' ksh 'foo psvar[0`uname>&2`]')
Linux
Beachten Sie, dass [ $# -gt 0 ]
es sich hierbei um einen weiteren Split+Glob-Aufruf handelt, der keinen Sinn ergibt (zumindest mit dem Standardwert von ist es weniger wahrscheinlich, dass er ein Problem darstellt $IFS
).
Antwort2
Haben Sie erwogen, den getopts
eingebauten Shell-Befehl zu verwenden, um Ihre Argumente zu analysieren (wie z. B. von @Stéphane Chazelas indieser Kommentar)? Das würde Ihnen viel Ärger ersparen.
In Ihrem Fall würde der entsprechende Code wie folgt aussehen:
while getopts "nbd:" argname
do
case "$argname" in
n) Var1="No" ;;
b) Var2="Backup" ;;
d) DirectoryName ="$OPTARG" ;;
?) echo -e "usage is..."
exit 1 ;;
esac
done