Bash-Skript zum Empfangen und Umleiten von zitierten Parametern

98

Ich versuche, zitierte Parameter eines Bash-Skripts abzurufen, damit sie sicher von einem verschachtelten Skript empfangen werden können. Irgendwelche Ideen?

test.sh

#!/bin/bash
echo $*
bash myecho.sh $*

myecho.sh

#!/bin/bash
 echo $1
 echo $2
 echo $3
 echo $4

Stichprobe:

bash test.sh aaa bbb '"ccc ddd"'

Ergebnis:

aaa bbb "ccc ddd"
aaa
bbb
"ccc
ddd"

Gewünschtes Ergebnis

aaa bbb "ccc ddd"
aaa
bbb
ccc ddd
chilltemp
quelle
2
Ich wollte gerade diese Frage stellen! Gutes Timing.
Scottie T

Antworten:

70
#!/bin/bash
echo $*
bash myecho.sh "$@"

Beachten Sie, dass das Konstrukt "$ @" nicht bash-spezifisch ist und mit jeder POSIX-Shell funktionieren sollte (zumindest mit Bindestrich). Beachten Sie auch, dass Sie angesichts der gewünschten Ausgabe überhaupt keine zusätzliche Zitierstufe benötigen. IE ruft einfach das obige Skript wie folgt auf:

./test.sh 1 2 "3 4"
Pixelbeat
quelle
5
"$ @" funktioniert mit jeder Bourne-Shell oder jedem Bourne-Shell-Derivat (ab 1978), einschließlich Korn und Bash. Wahrscheinlich ist in 95% der Fälle die Verwendung von "$ @" korrekt und $ * falsch.
Jonathan Leffler
Nett! Aber kennen Sie jemanden, wenn es eine Möglichkeit gibt, es "wie es ist" in einer Variablen zu speichern ? Original $@ist in einer Funktion nicht verfügbar (da es durch Funktionsargumente überschrieben wird). Ich habe versucht foovar="$@"und foovar=$@+ "$foovar"in der Funktion und keiner hat funktioniert: - /
Bitifet
143

Sie möchten "$ @" (in US-Dollar angegeben) verwenden, um Parameter an einen Index zu übergeben. Wie so ....

ls-color.sh:

#!/bin/bash
/bin/ls --color=auto "$@"    # passes though all CLI-args to 'ls'


Warum .....

Von der Bash-Manpage :

$*- Erweitert ab eins auf die Positionsparameter. Wenn die Erweiterung in doppelten Anführungszeichen erfolgt, wird sie zu einem einzelnen Wort erweitert, wobei der Wert jedes Parameters durch das erste Zeichen der IFS-Spezialvariablen getrennt ist. Das heißt, "$*"ist äquivalent zu "$1c$2c...", wobei c das erste Zeichen des Werts der IFS-Variablen ist. Wenn IFS nicht gesetzt ist, werden die Parameter durch Leerzeichen getrennt. Wenn IFS null ist, werden die Parameter ohne dazwischenliegende Trennzeichen verbunden.

$@- Erweitert ab eins auf die Positionsparameter. Wenn die Erweiterung in doppelten Anführungszeichen erfolgt, wird jeder Parameter zu einem separaten Wort erweitert. Das heißt, "$@"entspricht "$1" "$2" ...Wenn die doppelten Anführungszeichen Expansion innerhalb eines Wortes auftritt, wird die Ausdehnung des ersten Parameters mit dem Anfangsteil des ursprünglichen Wortes verbunden ist, und die Erweiterung des letzten Parameters wird mit dem letzten Teil der ursprünglichen verbundene Wort. Wenn es keine Positionsparameter gibt "$@"und $@zu nichts erweitert wird (dh sie werden entfernt).


Einrichten einiger Demoskripte ...

echo 'echo -e "\$1=$1\n\$2=$2\n\$3=$3\n\$4=$4"' > echo-params.sh
echo './echo-params.sh $*' > dollar-star.sh
echo './echo-params.sh $@' > dollar-at.sh
echo './echo-params.sh "$*"' > quoted-dollar-star.sh
echo './echo-params.sh "$@"' > quoted-dollar-at.sh
chmod +x *.sh

"$@"- Quoted-Dollar- At ist eine Identitätstransformation zum erneuten Übergeben von Argumenten an eine Subshell (~ 99% der Zeit war dies das, was Sie vorhatten):

./quoted-dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2=            
  # $3= 'cc cc'
  # $4= "ddd ddd"

"$*"- Der zitierte Dollar-Stern zerschmettert die Argumente in eine einzelne Zeichenfolge (~ 1% der Zeit, in der Sie dieses Verhalten tatsächlich möchten, z. B. unter bestimmten Bedingungen :) if [[ -z "$*" ]]; then ...:

./quoted-dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa  'cc cc' "ddd ddd"   
  # $2=                     
  # $3=             
  # $4=

$*/ $@- Ohne Anführungszeichen entfernen beide Formulare eine Anführungszeichen-Ebene und interpretieren Leerzeichen aus den zugrunde liegenden Zeichenfolgen, ignorieren jedoch Anführungszeichen (fast immer ist dies ein Fehler):

./dollar-star.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc                  
  # $3= cc'
  # $4= "ddd

./dollar-at.sh aaa '' "'cc cc'" '"ddd ddd"'
  # $1= aaa
  # $2= 'cc
  # $3= cc'
  # $4= "ddd

Wenn Sie Spaß haben möchten, können Sie "$ @" verwenden, um Dinge so tief zu verschachteln, wie Sie möchten, und Elemente vom Args-Stapel zu entfernen, wenn Sie möchten.

function identity() {
  "$@"
}
set -x
identity identity identity identity identity echo Hello \"World\"
# + identity identity identity identity identity echo Hello '"World"'
# + identity identity identity identity echo Hello '"World"'
# + identity identity identity echo Hello '"World"'
# + identity identity echo Hello '"World"'
# + identity echo Hello '"World"'
# + echo Hello '"World"'
# Hello "World"
Dave Dopson
quelle
1
Danke für die Erklärung. Ich habe gerade "$ *" für den Grep-Alias ​​verwendet.
Darkless
Du rettest meinen Tag!
XYZ