Frage

Ich habe einen Bash-Skript, wo ich will bestanden in den Argumenten Anführungszeichen halten.

Beispiel:

./test.sh this is "some test"

dann will ich diese Argumente verwenden und wiederverwenden sie, darunter Zitate und Zitate rund um die ganze Argument Liste.

Ich habe versucht \"$@\" verwenden, aber das entfernt die Anführungszeichen innerhalb der Liste.

Wie kann ich das erreichen?

War es hilfreich?

Lösung

Verwenden Sie einfach einfache Anführungszeichen um die Zeichenfolge mit den doppelten Anführungszeichen:

./test.sh this is '"some test"'

So sind die doppelten Anführungszeichen von innerhalb der einfachen Anführungszeichen auch als String interpretiert wurden.

Aber ich würde die gesamte Zeichenfolge zwischen einfachen Anführungszeichen zu setzen empfehlen:

 ./test.sh 'this is "some test" '

Um zu verstehen, was die Shell tut oder eher Argumente in Skripten zu interpretieren, können Sie ein kleines Skript wie folgt schreiben:

#!/bin/bash

echo $@
echo "$@"

Dann werden Sie sehen und zu testen, was los ist, wenn ein Skript mit verschiedenen Saiten Aufruf

Andere Tipps

"$@" verwendet, wird die Argumente als Liste ersetzen, ohne dass sie auf Leerzeichen neu aufzuteilen (sie wurden einmal geteilt, wenn das Shell-Skript aufgerufen wurde), die in der Regel genau das, was Sie wollen, wenn Sie wollen einfach nur die Argumente wieder passieren in ein anderes Programm.

Was sind Sie versuchen zu tun und in welcher Art und Weise ist es nicht?

Yuku Antwort nur funktioniert, wenn Sie der einzige Benutzer des Skripts sind, während Dennis Williamson ist toll, wenn Sie in erster Linie daran interessiert sind die Saiten in Druck, und erwarten, dass sie keine Zitate in Anführungszeichen haben.

Hier ist eine Version, die verwendet werden können, wenn alle Argumente als eine große quoted-String-Argument mit dem -c Parameter von bash oder su übergeben möchten:

#!/bin/bash
C=''
for i in "$@"; do 
    i="${i//\\/\\\\}"
    C="$C \"${i//\"/\\\"}\""
done
bash -c "$C"

So alle erhalten die Argumente ein Angebot um sie herum (harmlos, wenn es vorher nicht da war, für diesen Zweck), aber wir entkommen auch keine Fluchten und dann alle Zitate entkommen, die bereits waren in ein Argument (die Syntax ${var//from/to} tut globale Teilzeichenfolge Substitution).

Sie natürlich konnte nur wiederholen Sachen, die bereits Leerzeichen drin hatte, aber es wird hier keine Rolle. Ein Nutzen eines Skripts wie dieser in der Lage sein, eine bestimmte vordefinierte Reihe von Umgebungsvariablen zu haben (oder, mit su, Sachen als ein bestimmten Benutzer ausführen kann, ohne dass die Verwirrung der Doppel zitiert alles).


Update: Vor kurzem hatte ich Grund, dies mit minimalem Forking in eine POSIX Weise zu tun, die zu diesem Skript führen (die letzte printf dort gibt die Befehlszeile verwendet, um das Skript aufzuzurufen, die Sie sollten in Kopieren-Einfügen der Lage sein, bestellen sie mit den entsprechenden Argumenten aufzurufen):

#!/bin/sh
C=''
for i in "$@"; do
    case "$i" in
        *\'*)
            i=`printf "%s" "$i" | sed "s/'/'\"'\"'/g"`
            ;;
        *) : ;;
    esac
    C="$C '$i'"
done
printf "$0%s\n" "$C"

Ich wechselte '' da Muscheln auch Dinge wie $ und !! in ""-Zitate interpretieren.

Wenn es sicher ist, die Annahme zu machen, dass ein Argument, das Leerraum enthält gewesen sein muss (und sollte) zitiert, dann können Sie sie wie folgt hinzufügen:

#!/bin/bash
whitespace="[[:space:]]"
for i in "$@"
do
    if [[ $i =~ $whitespace ]]
    then
        i=\"$i\"
    fi
    echo "$i"
done

Hier ist ein Probelauf:

$ ./argtest abc def "ghi jkl" $'mno\tpqr' $'stu\nvwx'
abc
def
"ghi jkl"
"mno    pqr"
"stu
vwx"

Sie können auch Einsatz wörtlich Tabs und Zeilenumbrüche mit Strg - V Tab und Strg - V Strg -. J in doppelten oder einfachen Anführungszeichen statt entkommen innerhalb $'...' der mit

Ein Hinweis auf Einfügen Zeichen in Bash: Wenn Sie Vi Tastenbelegungen (set -o vi) in Bash verwenden (Emacs ist die Standard - set -o emacs), Sie müssen sich sein einfügen Modus um Zeichen einfügen . Im Emacs-Modus sind Sie immer im Einfügemodus.

Es gibt zwei sichere Wege, dies zu tun:

1. Shell Parameter Expansion : ${variable@Q}:

Wenn Sie eine Variable über ${variable@Q} erweitert:

  

Die Erweiterung ist ein String, der Wert des Parameters in einem Format angegeben ist, die als Eingabe wiederverwendet werden können.

Beispiel:

$ expand-q() { for i; do echo ${i@Q}; done; }  # Same as for `i in "$@"`...
$ expand-q word "two words" 'new
> line' "single'quote" 'double"quote'
word
'two words'
$'new\nline'
'single'\''quote'
'double"quote'

2. printf %q "$quote-me"

printf unterstützt zitiert intern. Die manuellen Einzug für printf sagt:

  

%q Verursacht printf das entsprechende Argument in einem Format auszugeben, die als Shell-Eingang wieder verwendet werden können.

Beispiel:

$ cat test.sh 
#!/bin/bash
printf "%q\n" "$@"
$ 
$ ./test.sh this is "some test" 'new                                                                                                              
>line' "single'quote" 'double"quote'
this
is
some\ test
$'new\nline'
single\'quote
double\"quote
$

Beachten Sie die zweite Art und Weise etwas sauberer ist, wenn der zitierte Text an einen Menschen darzustellen.

Siehe auch: Für bash, POSIX sh und zsh: Quote String mit einfachen Anführungszeichen statt Schrägstriche

Wie Tom Hale sagte, eine Möglichkeit, dies mit printf zu tun %q mit zitieren-escape.

Zum Beispiel:

send_all_args.sh

#!/bin/bash
if [ "$#" -lt 1 ]; then
 quoted_args=""
else
 quoted_args="$(printf " %q" "${@}")"
fi

bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_args}"

send_fewer_args.sh

#!/bin/bash
if [ "$#" -lt 2 ]; then
 quoted_last_args=""
else
 quoted_last_args="$(printf " %q" "${@:2}")"
fi

bash -c "$( dirname "${BASH_SOURCE[0]}" )/receiver.sh${quoted_last_args}"

receiver.sh

#!/bin/bash
for arg in "$@"; do
  echo "$arg"
done

Beispiel Nutzung:

$ ./send_all_args.sh
$ ./send_all_args.sh a b
a
b
$ ./send_all_args.sh "a' b" 'c "e '
a' b
c "e 
$ ./send_fewer_args.sh
$ ./send_fewer_args.sh a
$ ./send_fewer_args.sh a b
b
$ ./send_fewer_args.sh "a' b" 'c "e '
c "e 
$ ./send_fewer_args.sh "a' b" 'c "e ' 'f " g'
c "e 
f " g

Ich brauchte diese für alle Argumente an einem anderen Dolmetscher weitergeleitet werden. Was für mich richtig gelandet ist:

bash -c "$(printf ' %q' "$@")"

Beispiel (wenn sie als forward.sh genannt):

$ ./forward.sh echo "3 4"
3 4
$ ./forward.sh bash -c "bash -c 'echo 3'"
3

(Natürlich ist das eigentliche Skript Ich benutze ist komplexer, an denen in meinem Fall nohup und Umleitungen etc., aber dies ist der Schlüssel Teil).

Mein Problem war ähnlich und ich gemischte Ideen hier gepostet.

Wir haben einen Server mit einem PHP-Skript, die E-Mails sendet. Und dann haben wir einen zweiten Server, die über SSH auf den ersten Server verbindet und führt sie aus.

Der Skript Name ist das gleiche auf beiden Servern und beide sind eigentlich über einen Bash-Skript ausgeführt wird.

Auf Server 1 (local) Bash-Skript haben wir nur:

/usr/bin/php /usr/local/myscript/myscript.php "$@"

Dieses befindet sich auf /usr/local/bin/myscript und wird von dem Remote-Server genannt. Es funktioniert gut, auch für Argumente mit Leerzeichen.

Aber dann auf dem Remote-Server können wir nicht die gleiche Logik verwenden, da der erste Server nicht die Zitate von "$@" erhalten. Früher habe ich die Ideen von JohnMudd und Dennis Williamson die Optionen und Parameter-Array mit den Zitaten neu zu erstellen. Ich mag die Idee der Zugabe von nur entkommen Zitaten, wenn das Element Leerzeichen enthält.

So der Remote-Skript läuft mit:

CSMOPTS=()
whitespace="[[:space:]]"
for i in "$@"
do
    if [[ $i =~ $whitespace ]]
    then
        CSMOPTS+=(\"$i\")
    else
        CSMOPTS+=($i)
    fi
done

/usr/bin/ssh "$USER@$SERVER" "/usr/local/bin/myscript ${CSMOPTS[@]}"

Beachten Sie, dass ich "${CSMOPTS[@]}" verwenden, um die Optionen Array an den Remote-Server zu übergeben.

Danke für eveyone, die hier gepostet! Es hat mir wirklich geholfen! :)

unhammer 's Beispiel Array zu verwenden.

printargs() { printf "'%s' " "$@"; echo; };  # http://superuser.com/a/361133/126847

C=()
for i in "$@"; do
    C+=("$i")  # Need quotes here to append as a single array element.
done

printargs "${C[@]}"  # Pass array to a program as a list of arguments.                               

Zitate von Bash interpretiert werden und nicht in Befehlszeilenargumenten oder Variablenwert gespeichert.

Wenn Sie zitierten Argumente verwenden möchten, müssen Sie sie jedes Mal, wenn Sie sie verwenden zitieren:

val="$3"
echo "Hello World" > "$val"

Verwenden Sie einfach:

"${@}"

Zum Beispiel:

# cat t2.sh
for I in "${@}"
do
   echo "Param: $I"
done
# cat t1.sh
./t2.sh "${@}"

# ./t1.sh "This is a test" "This is another line" a b "and also c"
Param: This is a test
Param: This is another line
Param: a
Param: b
Param: and also c

Ja, so scheint, dass es nicht möglich ist, immer die Zitate zu bewahren, sondern auch für die Frage, die ich mit ihm zu tun hatte war nicht erforderlich.

Ich habe eine Bash-Funktion, die nach unten Ordner für einen String rekursiv und grep suchen, ist das Problem ein String übergeben, die Leerzeichen, wie „finden Sie diese Zeichenfolge“ hat. dies dem Bash-Skript Passing wird dann die Basis Argument $ n nehmen und es grep übergeben, hat diese grep diese verschiedenen Argumente zu glauben. Die Art, wie ich dieses Problem gelöst, indem Sie die Tatsache, dass, wenn Sie bash zitieren die Funktion es Gruppen die Elemente in Anführungszeichen in ein einziges Argument zu nennen. Ich brauchte nur dieses Argument mit Zitaten dekorieren und an den Befehl grep übergeben.

Wenn Sie wissen, was Sie Argument in der Bash erhalten, die Angebote für seinen nächsten Schritt muss, kann man nur mit mit Zitaten schmückt.

Wie Gary S. Weaver in seinem Quellcode Tipp gezeigt, der Trick ist, bash mit dem Parameter '-c' nennen und dann die nächsten zitieren.

z.

bash -c "<your program> <parameters>"

oder

docker exec -it <my docker> bash -c "$SCRIPT $quoted_args"

Wenn Sie alle Argumente zu übergeben bash aus einer anderen Programmiersprache (zum Beispiel, wenn Sie wollen würden bash -c oder emit_bash_code | bash auszuführen), verwenden Sie diese:

  • entkommen alle Apostrophe Sie mit '\'' haben.
  • dann, umgibt das Ergebnis mit singulären Anführungszeichen

Das Argument von abc'def wird somit zu 'abc'\''def' umgewandelt werden. Die Zeichen '\'' interpretiert werden, wie folgend:. Die bereits bestehende zitiert wird mit dem ersten ersten Zitat beendet, dann wird die entkam singulären Apostroph \' kommt, dann werden die neuen zitieren beginnt

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top