Bash Expansion Mystery - PullRequest
       23

Bash Expansion Mystery

0 голосов
/ 18 ноября 2018

Это очень «популярная» тема по stackoverflow, и, к сожалению, я не смог выяснить это, рассматривая другие вопросы.В любом случае давайте рассмотрим следующий сценарий.Функция получает набор строковых аргументов, например, так: some_function "give some" "string arguments" Первое, что делает эта функция, это помещает эти аргументы в массив так, что, например, array [0] дает «give some», а array [1] дает «string arguments»

Теперь допустим, у меня есть массив строк some_array и я хочу вызвать some_function для него.Как мне «преобразовать» этот массив, чтобы он работал?

Вот несколько примеров, которые НЕ работают:

function print_args() {
  local arr=( "$@" )
  i=0;
  for item in "${arr[@]}"
  do
    echo "[$i] -> '$item'"
    (( i++ ))
  done
}

echo "example"
print_args "this is" "the desired" "behavior"
echo -e "----------------\n"

some_array=( "\"does NOT\""  "\"seem to\"" "\"work\"" )
stringified_array=$(printf "%s " "${some_array[@]}")
echo "stringified array: [$stringified_array]"

echo "1) passing \$some_array"
print_args $some_array
echo -e "---------------------------\n"

echo "2) passing \"\$some_array\""
print_args "$some_array"
echo -e "---------------------------\n"

echo "3) passing \$stringified_array"
print_args $stringified_array
echo -e "---------------------------\n"

echo "4) passing \"\$stringified_array\""
print_args "$stringified_array"
echo -e "---------------------------\n"

и вот вывод

example
[0] -> 'this is'
[1] -> 'the desired'
[2] -> 'behavior'
----------------

stringified array: ["does NOT" "seem to" "work" ]
1) passing $some_array
[0] -> '"does'
[1] -> 'NOT"'
---------------------------

2) passing "$some_array"
[0] -> '"does NOT"'
---------------------------

3) passing $stringified_array
[0] -> '"does'
[1] -> 'NOT"'
[2] -> '"seem'
[3] -> 'to"'
[4] -> '"work"'
---------------------------

4) passing "$stringified_array"
[0] -> '"does NOT" "seem to" "work" '
---------------------------

Я думаю, что я понимаю 1) и 2) и только попробовал их из отчаяния.Я считаю, что я понимаю 4), а также.Теперь моя большая проблема заключается в том, что я не понимаю, что, черт возьми, происходит с 3) и, что более важно, как я могу «структурировать» свой массив, чтобы достичь того, чего я хочу.Важным примечанием здесь является то, что я хотел бы попробовать и избежать использования eval.

Спасибо!

1 Ответ

0 голосов
/ 19 ноября 2018

Вы можете ожидать, что говорите с 3):

print_args "does NOT" "seem to" "work"

но на самом деле 3) эквивалентно:

print_args '"does' 'NOT"' '"seem' 'to"' '"work"'

это потому, что переменная без кавычек $stringified_array разбивается на слова в IFS перед тем, как передается функции. Двойные кавычки в строке являются лишь частью строки и не работают для кавычек пробелов.

Попытайтесь увидеть, что происходит, изменив строку # 16- # 17 в вашем примере кода с помощью:

16c16
< stringified_array=$(printf "%s " "${some_array[@]}")
---
> stringified_array=$(printf "%s#" "${some_array[@]}")
17a18
> IFS=#

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

...