Как сохранить кавычки в аргументах Bash?
у меня есть скрипт Bash, где я хочу сохранить кавычки в переданных аргументах.
пример:
./test.sh this is "some test"
затем я хочу использовать эти аргументы и повторно использовать их, включая кавычки и кавычки вокруг всего списка аргументов.
Я пробовал использовать "$@", но это удаляет кавычки внутри списка.
Как мне это сделать?
11 ответов:
просто используйте одинарные кавычки вокруг строки с двойными кавычками:
./test.sh this is '"some test"'таким образом, двойные кавычки внутри одинарных кавычек также интерпретировались как строка.
но я бы рекомендовал поместить всю строку между одинарными кавычками:
./test.sh 'this is "some test" 'чтобы понять, что делает оболочка или, скорее, интерпретирует аргументы в скриптах, вы можете написать небольшой скрипт следующим образом:
#!/bin/bash echo $@ echo "$@"тогда вы увидите и проверить, что происходит при вызове скрипта с разными строками
С помощью
"$@"будет заменять аргументы в виде списка, без повторного разбиения их на пробелы (они были разделены один раз, когда был вызван сценарий оболочки), что, как правило, именно то, что вы хотите, если вы просто хотите повторно передать аргументы в другую программу.что вы пытаетесь сделать и каким образом это не работает?
ответ Yuku работает только в том случае, если вы единственный пользователь своего сценария, в то время как Деннис Уильямсон отлично подходит, если вы в основном заинтересованы в печати строк и ожидаете, что у них не будет кавычек в кавычках.
вот версия, которую можно использовать, если вы хотите передать все аргументы в виде одного большого аргумента в кавычках %s\n" "$C"
я переключился на
''поскольку оболочки также интерпретируют такие вещи, как$и!!на""-цитаты.
если можно с уверенностью предположить, что аргумент, содержащий пробел, должен быть (и должен быть) заключен в кавычки, то вы можете добавить их следующим образом:
#!/bin/bash whitespace="[[:space:]]" for i in "$@" do if [[ $i =~ $whitespace ]] then i=\"$i\" fi echo "$i" doneвот пример запуска:
$ ./argtest abc def "ghi jkl" $'mno\tpqr' $'stu\nvwx' abc def "ghi jkl" "mno pqr" "stu vwx"вы можете вставить литеральные вкладки и новые строки с помощью Ctrl -VTab и Ctrl -VCtrl -J в двойных или одинарных кавычках вместо того, чтобы использовать escapes внутри
$'...'.Примечание вставка символы в Bash: если вы используете привязки клавиш Vi (
set -o vi) в Bash (Emacs по умолчанию -set -o emacs), вы должны быть в вставить режим чтобы вставить символы. В режиме Emacs вы всегда находитесь в режиме вставки.
есть два безопасных способа сделать это:
1. расширение параметров оболочки:
${variable@Q}:при расширении переменной через
${variable@Q}:расширение представляет собой строку, которая является значением параметра указаны в формате, который может быть использован в качестве входных данных.
пример:
$ 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поддерживает цитирование внутренне. Элемент запись в руководстве дляprintfговорит:
%qзаставляет printf выводить соответствующий аргумент в формате, который может быть повторно использован в качестве ввода оболочки.пример:
$ 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 $
примечание 2-й способ немного чище, если отображение цитируемого текста для человека.
связанные: для bash, POSIX sh и zsh:строка кавычек с одинарными кавычками, а не с обратной косой чертой
как сказал том Хейл, один из способов сделать это-с
printfиспользуя%qцитировать-побег.например:
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пример использования:
$ ./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
изменить unhammerпример использования массива.
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.
моя проблема была похожа, и я использовал смешанные идеи, размещенные здесь.
у нас есть сервер с PHP скриптом, который отправляет электронную почту. И тогда у нас есть второй сервер, который подключается к 1-му серверу через SSH и выполняет его.
имя скрипта одинаково на обоих серверах, и оба они фактически выполняются с помощью сценария bash.
на сервере 1 (локальный) скрипт bash у нас есть только:
/usr/bin/php /usr/local/myscript/myscript.php "$@"это находится на
/usr/local/bin/myscriptи вызывается удаленным сервером. Оно прекрасно работает даже для Аргументов с пробелами.но тогда на удаленном сервере, мы не можем использовать ту же логику, потому что 1-й сервер не получает котировки от
"$@". Я использовал идеи от JohnMudd и Dennis Williamson, чтобы воссоздать массив опций и параметров с цитатами. Мне нравится идея добавления экранированных цитат только тогда, когда в элементе есть пробелы.таким образом, удаленный скрипт работает с:
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[@]}"обратите внимание, что я использую
"${CSMOPTS[@]}"для прохождения массив параметров для удаленного сервера.Спасибо за все, что выложили здесь! Это действительно помогло мне! :)
мне это было нужно для пересылки всех аргументов другому интерпретатору. Что оказалось правильным для меня:
bash -c "$(printf ' %q' "$@")"пример (при имени как forward.sh):
$ ./forward.sh echo "3 4" 3 4 $ ./forward.sh bash -c "bash -c 'echo 3'" 3(конечно, фактический скрипт, который я использую, более сложен, включая в моем случае nohup и перенаправления и т. д. но это ключевая часть.)
кавычки интерпретируются bash и не хранятся в аргументах командной строки или значениях переменных.
Если вы хотите использовать процитировал аргументы, вы должны цитировать их каждый раз, когда вы их используете:
val="" echo "Hello World" > "$val"
да, кажется, что невозможно когда-либо сохранить цитаты, но для вопроса, с которым я имел дело, это не было необходимо.
У меня есть функция bash, которая будет рекурсивно искать папку вниз и grep для строки, проблема заключается в передаче строки, которая имеет пробелы, такие как "найти эту строку". Передача этого скрипту bash затем возьмет базовый аргумент $n и передаст его grep, у этого есть grep, полагающий, что это разные аргументы. Как я решил это, используя факт что когда вы цитируете bash для вызова функции, она группирует элементы в кавычках в один аргумент. Мне просто нужно было украсить этот аргумент кавычками и передать его команде grep.
Если вы знаете, какой аргумент вы получаете в bash, который нуждается в кавычках для своего следующего шага, вы можете просто украсить кавычками.
Comments