bash: заполнение массива элементами, содержащими пробелы и специальные символы

Я хочу иметь возможность заполнять элементы массива произвольными строками, т. е. строки, которые могут содержать \ и пробелы, например. Я написал это:

#!/bin/bash
function populate_array () {
    if [ "$#" -gt 0 ] ; then
        # Enter array w/ elements as argument of executable 
        array=($@)
        n=$#
    else
        # Invoke executable with no arg,, enter array element later
        read -p "Enter array elements separated by spaces: " -a array  
        n=${#array[@]} 
    fi
    printf "%d array elements \n" "$n"
} 

populate_array "$@"

while (("$n" > 0))   # while [ "$n" -gt 0 ] ALSO WORKS
do
    printf "%s \n" "${array[$n-1]}"
    n=$n-1
done
exit 0

Блок while предназначен только для проверки элементов массива. Функция достаточно проста, чтобы хорошо работать для аргументов, которые не содержат space или \. Не иначе.

Попытка ввода аргументов исполняемому файлу как:

#!> bash [scriptname] lkl1239 343.4l 3,344 (34) "lklk  lkl" lkaa\ lkc

Я бы хотел увидеть 6 аргументов:

lkl1239
343.4l 
3,344
(34)
lklk  lkl
lkaa lkc

Вместо этого я получаю бросок:

Для ( => bash: синтаксическая ошибка около неожиданного токена `34 'Пространство, содержащее строки, интерпретируется как строки x + 1, где x - количество непересекающихся пробелов ни в начале, ни в конец строки. Баш игнорирует то, что происходит после первого появления \

Как это делается?

1
задан 18 June 2015 в 18:04

3 ответа

Просто укажите $@, как вы уже правильно сделали в вызове функции:

array=("$@")

Как man bash ставит:

"$@" эквивалентно [ f5]
1
ответ дан 23 May 2018 в 19:42

Специальные символы, как правило, должны быть экранированы с помощью обратного слэша, например:

 $ array-script.sh   lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc                                                                  
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 

Скобки обрабатываются оболочкой как метасимволы, поэтому необходимо экранировать. Обратная косая черта в lkaa \ lkc уже ускользает от промежутка между lkaa и lkc, поэтому эти две строки рассматриваются как одна. То же, что и с cd /home/user/bin/NAME\ WITH\ SPACE

И из man bash:

   metacharacter
                  A character that, when unquoted, separates words.  One of the following:
                  |  & ; ( ) < > space tab
0
ответ дан 23 May 2018 в 19:42
  • 1
    В этом случае работают одиночные кавычки? Я читал, что Баш интерпретирует вещи внутри одной кавычки как литералы, а не интерпретирует ее. (I.E. 'foo foobar foo\bar\baz 66@SUDO' можно прочитать как эти три элемента? Проблема состоит в одинарных кавычках, хотя в элементе ...) – Thomas Ward♦ 18 June 2015 в 17:32
  • 2
    @ThomasW. ставя одинарные кавычки вокруг всей строки, как вы показали, делает сценарий обработкой всей строки как одного элемента, и да, это заставляет обрабатывать элементы как литералы. Поэтому каждый отдельный элемент должен быть одинарным. – Sergiy Kolodyazhnyy 18 June 2015 в 17:35
  • 3
    Неа. хочу 6 массивов, а не 7 – Cbhihe 18 June 2015 в 21:45
  • 4
    Hm, без дополнительной обратной косой черты в lkaa \ lkc, которая дает 6 – Sergiy Kolodyazhnyy 18 June 2015 в 21:51
  • 5
    Я думаю, это потому, что lkaa \ lkc служит для самозащиты пространства между двумя строками, поэтому он превращается в одну строку с пространством – Sergiy Kolodyazhnyy 18 June 2015 в 21:52

вы можете попробовать, поставив ниже в верхней части скрипта

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

и

IFS=$SAVEIFS 

в нижней части скрипта

0
ответ дан 23 May 2018 в 19:42

Другие вопросы по тегам:

Похожие вопросы: