2016-12-24 3 views
3

data.in:Bash: Разделить строку в кавычках в массив

a b c 'd e' 

script.sh:

while read -a arr; do 
    echo "${#arr[@]}" 
    for i in "${arr[@]}"; do 
     echo "$i" 
    done 
done 

Команда:

cat data.in | bash script.sh 

Выход:

5 
a 
b 
c 
'd 
e' 

Вопрос:

Как я могу получить 'd e' как отдельный элемент в массиве?


Обновление. Это лучшее, что я сделал до сих пор:

while read line; do 
    arr=() 
    while read word; do 
     arr+=("$word") 
    done < <(echo "$line" | xargs -n 1) 
    echo "${#arr[@]}" 
    for i in "${arr[@]}"; do 
     echo "$i" 
    done 
done 

Выход:

4 
a 
b 
c 
d e 

Однако следующий data.in:

"a\"b" c 

не сможет его (и любой другой сценарий, у меня есть найденных до настоящего времени, даже в dup question):

xargs: unmatched double quote; by default quotes are special to xargs unless you use the -0 option 

Но этот вход является законным, потому что вы можете ввести в командной строке:

echo "a\"b" c 

И это хорошо работает. Так что это несоответствие в поведении, а не незаконный ввод.

+2

Правильный ответ здесь заключается в использовании 'xargs printf '% s \ 0'' для синтаксического анализа вашей строки в потоке с разделителем NUL, который bash может читать однозначно. ('xargs', когда не использует расширения' -d' или '-0', использует правила разбора, подобные оболочке, для разделения ввода на слова). См., В частности, http://stackoverflow.com/a/31485948/14122 –

+0

Я думаю, что этот вопрос лучше справляется с выражением проблемы в MCVE, чем дубликат, на который он ссылается. +1 для этого. Кроме того, Чарльз, Тим Тоэди. Я бы предложил другой маршрут, если бы этот вопрос был открыт для ответов, кроме вашего. – ghoti

+0

@ghoti, а? Я вообще не ответил на этот вопрос (только комментарий, и вы тоже можете предоставить свои собственные), а связанный вопрос * * открыт. Я был бы рад увидеть там правильный ответ. –

ответ

0
$ eval "a=($(cat data.in))" 
$ for i in "${a[@]}";do echo "|$i|";done 
|a| 
|b| 
|c| 
|d e| 
$ 
+0

Это опасно: если ваш 'data.in' содержит' $ (rm -rf ~) ', вы не хотите, чтобы это выполнено. –

+0

BTW, 'printf '|% s | \ n'" $ {a [@]} "будет печатать ваш массив в данной форме без цикла. –

+0

... еще одна проблема заключается в том, что если у вас есть '*' в вашем 'data.in', вы обязательно хотите' * 'на выходе, а не список имен в текущем каталоге. –

Смежные вопросы