Как разделить строку с помощью кавычек (как аргументы команды) в bash?

Как разделить строку с помощью кавычек (как аргументы команды) в bash?

У меня есть такая строка:

"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"

Я хочу иметь возможность разделить это следующим образом:

aString that may haveSpaces IN IT
bar
foo
bamboo  
bam boo

Как это сделать? (предпочтительно в одну строку)

решение1

Когда я увидел ответ Дэвида Постилла, я подумал: «Должно быть более простое решение». После некоторых экспериментов я нашел следующие работы:-

string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo $string
eval 'for word in '$string'; do echo $word; done'

Это работает, потому что evalрасширяет строку (удаляя кавычки и расширяя string) перед выполнением результирующей строки (которая является встроенным ответом):

for word in "aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"; do echo $word; done

Альтернативный вариант, который расширяется до той же строки:

eval "for word in $string; do echo \$word; done"

Здесь stringраскрывается в двойных кавычках, но необходимо $экранировать, чтобы wordне раскрываться до выполнения строки (в другой форме использование одинарных кавычек имеет тот же эффект). Результаты таковы:-

[~/]$ string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
[~/]$ echo $string
"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"
[~/]$ eval 'for word in '$string'; do echo $word; done'
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo
[~/]$ eval "for word in $string; do echo \$word; done"
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo

решение2

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

eval "array=($string)"

for arg in "${array[@]}"; do echo "$arg"; done   

ps Пожалуйста, оставьте комментарий, если вы найдете более простой способ без eval.

Редактировать:

Основываясь на ответе @Hubbitus, мы имеем полностью очищенную и правильно цитируемую версию. Примечание: это излишество и фактически оставит дополнительные обратные косые черты в разделах с двойными или одинарными кавычками, предшествующих большинству знаков препинания, но неуязвимо для атак.

declare -a "array=($( echo "$string" | sed 's/[][`~!@#$%^&*():;<>.,?/\|{}=+-]/\\&/g' ))"

Я оставляю заинтересованным читателям возможность изменять текст по своему усмотрению.http://ideone.com/FUTHhj

решение3

Похоже, xargs справляется с этим довольно хорошо:

$ a='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
$ printf "%s" "$a" | xargs -n 1 printf "%s\n"
aString that may haveSpaces IN IT
bar
foo
bamboo
bam boo

решение4

Вы можете сделать это вместо declare, evalнапример:

Вместо:

string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo"'
echo "Initial string: $string"
eval 'for word in '$string'; do echo $word; done'

Делать:

declare -a "array=($string)"
for item in "${array[@]}"; do echo "[$item]"; done

Но учтите, что ввод данных пользователем не намного безопаснее!

Итак, если вы попробуете это, скажем, со строкой:

string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo" `hostname`'

Вас hostnameоценивают (конечно, может быть что-то вроде rm -rf /)!

Очень-очень простая попытка защитить его, просто замените символы вроде ` и $:

string='"aString that may haveSpaces IN IT" bar foo "bamboo" "bam boo" `hostname`'
declare -a "array=( $(echo $string | tr '`$<>' '????') )"
for item in "${array[@]}"; do echo "[$item]"; done

Теперь вы получили такой вывод:

[aString that may haveSpaces IN IT]
[bar]
[foo]
[bamboo]
[bam boo]
[?hostname?]

Более подробную информацию о методах, плюсах и минусах вы можете найти в этом хорошем ответе:https://stackoverflow.com/questions/17529220/почему-следует-избегать-этого-в-баше-и-что-следует-использовать-вместо-этого/17529221#17529221

Но вектор для атаки все равно остался. Я очень хочу иметь в bash метод кавычек строк, как в двойных кавычках ("), но без интерпретации содержимого.

Связанный контент