Объедините все аргументы и заключите их в двойные кавычки - PullRequest
17 голосов
/ 23 июня 2010
function foo() {
A=$@...
echo $A
}

foo bla "hello ppl"

Я бы хотел, чтобы результат был:"bla" "hello ppl"

Что мне нужно сделать вместо многоточия?

Ответы [ 6 ]

23 голосов
/ 23 июня 2010

@ msw имеет правильную идею (в комментариях к вопросу). Однако есть еще одна идея для печати аргументов с кавычками: использовать неявную итерацию printf:

foo() { printf '"%s" ' "$@"; echo ""; }

foo bla "hello ppl"
# => "bla" "hello ppl"
6 голосов
/ 23 июня 2010

Используйте подстановку параметров для добавления "в качестве префикса и суффикса:

function foo() {
    A=("${@/#/\"}")
    A=("${A[@]/%/\"}")
    echo -e "${A[@]}"
}

foo bla "hello ppl" kkk 'ss ss'

выход

"bla" "hello ppl" "kkk" "ss ss"
3 голосов
/ 23 июня 2010

ninjalj имел правильную идею, но использование кавычек было странным, отчасти потому, что то, что запрашивает OP, на самом деле не лучший выходной формат для многих задач оболочки.На самом деле, я не могу понять, для чего предназначена эта задача, но:

function quote_args {
   for i ; do
      echo \""$i"\"
   done
}

помещает свои аргументы в кавычках по одному на строку, что обычно является наилучшим способом подачи других программ.Вы получаете вывод в форме, которую вы не просили:

$ quote_args this is\ a "test really"
"this"
"is a"
"test really"

, но ее можно легко преобразовать, и именно эту фразу предпочитают большинство вызовов оболочки:

$ echo `quote_args this is\ a "test really"`
"this" "is a" "test really"

но если он не пройдет еще один eval проход, дополнительные кавычки, вероятно, испортят ситуацию.Таким образом, ls "is a file" выведет список файлов is a file, а

$ ls `quote_args is\ a\ file`

попытается перечислить "is, a и file", которые вы, вероятно, не хотите.

3 голосов
/ 23 июня 2010

Вы можете использовать «$ @» для обработки каждого параметра как отдельного параметра, а затем выполнить цикл по каждому параметру:

function foo() {
for i in "$@"
do
    echo -n \"$i\"" "
done
echo
}

foo bla "hello ppl"
2 голосов
/ 23 июня 2010

Не требуется петля:

foo() { local saveIFS=$IFS; local IFS='"'; local a="${*/#/ \"}"; echo "$a"\"; IFS=$saveIFS; }

Сохранение IFS в этом простом примере не требуется, особенно восстановление его непосредственно перед закрытием функции, поскольку используется local. Однако я включил его на случай, если в функцию войдут другие вещи, на которые может повлиять измененный IFS.

Пример выполнения:

$ foo a bcd "efg hij" k "lll mmm nnn " ooo "   ppp   qqq   " rrr\ sss
 "a" "bcd" "efg hij" "k" "lll mmm nnn " "ooo" "   ppp   qqq   " "rrr sss"
1 голос
/ 06 марта 2016

Единственное решение, которое учитывает обратную косую черту и кавычки внутри аргумента:

$ concatenate() { printf "%q"" " "$@"; echo ""; }
$ concatenate arg1 "arg2" "weird arg3\\\\\\bbut\" legal!"
arg1 arg2 weird\ arg3\\\\\\bbut\"\ legal\!

Обратите внимание на "% q" ""

% q ARGUMENT печатается в формате, который можно использовать в качестве оболочки ввод, экранирование непечатаемых символов с помощью предлагаемый синтаксис POSIX $ ''.

Специальные символы (\, \b backspace, ...) действительно будут интерпретироваться принимающей программой, даже если они не отображаются, интерпретируются в выводе терминала.

Давайте проверим:

# display.sh: Basic script to display the first 3 arguments passed
echo -e '#!/bin/bash'"\n"'echo -e "\$1=""$1"; echo -e "\$2=""$2"; echo -e "\$3=""$3"; sleep 2;' > display.sh
sudo chmod 755 display.sh

# Function to concatenate arguments as $ARGS
# and "evalutate" the command display.sh $ARGS
test_bash() { ARGS=$(concatenate "$@"); bash -c "./display.sh ""$ARGS"; }

# Test: Output is identical whatever the special characters
./display.sh arg1 arg2 arg3
test_bash    arg1 arg2 arg3

Более сложный тест:

./display.sh arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"
test_bash    arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-"

В display.sh мы используем echo -e вместо просто echo или printf для интерпретации специальных символов. Это только репрезентативно, если ваша вызываемая программа их интерпретирует.

-e включить интерпретацию обратной косой черты

Если действует -e, распознаются следующие последовательности:

  • \ обратный слеш
  • \ оповещение (BEL)
  • \ b Backspace
  • 1044 * Etc. *

NB: \b является символом возврата, поэтому в примере он удаляет Y.

Обратите внимание, что этот пример не должен воспроизводиться в реальном коде:

Благодаря принятому ответу и Дэнни Хонгу ответ в разделе «Как избежать двойной кавычки внутри двойной кавычки?»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...