LINUX.ORG.RU

[bash] Разбор строк в цикле

 


0

0

Можно ли в цикле правильно разобрать строку,
содержащую двойные кавычки как ограничители элементов? Например:

strVar="\"раз два\" \"три\""
for item in $strVar; do
    echo $item
done

Этот цикл даёт не тот результат, который хотелось бы:
получается три итерации, а не две, т.к.
for разбирает строку по пробелам, а на кавычки ему наплевать.

Ещё один вопрос по той же теме. Разбор многострочного текста в цикле:

strVar="раз\nдва\nтри"
myVar=""
echo -e $strVar | while read line; do
    myVar=$myVar$line
    echo $myVar" (внутри цикла)"
done
echo $myVar" (после цикла)"

Наращивать переменную myVar в цикле можно, но бесполезно,
т.к. на выходе цикла она недоступна.
Возможно, это происходит из-за конвейера, который побуждает bash
создать подпроцесс оболочки для цикла,
а экспортировать переменные "вверх" не удаётся.

Можно попробовать "пристроиться сзади",
чтобы не использовать конвейер, т.е. что-то вроде такого:

strVar="раз\nдва\nтри"
while read line; do
    myVar=$myVar$line
    echo $myVar" (внутри цикла)"
done < $strVar

Но это не работает вообще, т.к. здесь bash хочет файл,
а не переменную.
Есть ли вариант решения проблемы?

The_gray_Cardinal
() автор топика
Ответ на: комментарий от borisych

>> IFS="\""; strVar="\"раз два\" \"три\""; for item in $strVar;do echo $item;done

Спасибо! То, что надо.

The_gray_Cardinal
() автор топика
Ответ на: комментарий от The_gray_Cardinal

>Возможно, это происходит из-за конвейера, который побуждает bash

Именно так, направляйте вывод цикла в файл или в переменную.

mky ★★★★★
()
Ответ на: комментарий от mky

>> Именно так, направляйте вывод цикла в файл или в переменную.

Не понял, что значит "направить вывод цикла в переменную".
Можно пример, как это выглядит в коде?

The_gray_Cardinal
() автор топика
Ответ на: комментарий от The_gray_Cardinal

Как оказалось, тема исчерпана не совсем.
Можно ли разобрать в цикле многострочный текст, используя IFS="\n"?
У меня не выходит, разделителем оказывается почему-то буква "n",
а не перевод строки. И пример скрипта для Nautilus:

IFS="\n"
for line in "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"; do
    if [ ${#line} -gt 0 ]; then
        zenity --info --text="$line" --title='Передан файл:'
    fi
done

Здесь вообще разбора не происходит,
вся строка захватывается в первой итерации цикла.

The_gray_Cardinal
() автор топика
Ответ на: комментарий от anonymous

>> IFS='
>> '
У меня это не работает. Вот так не работает тоже:
IFS="\
"

The_gray_Cardinal
() автор топика
Ответ на: комментарий от mky

>> IFS=$'\n' Одиночные кавычки и знак доллара перед ними. И, возможно, нужен будет export IFS.

Не работает. Ни с экспортом, ни без него.
Во всяком случае, для разбора $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS.

The_gray_Cardinal
() автор топика
Ответ на: комментарий от The_gray_Cardinal

Не знаю, почему у вас не работает. Может вы забыли #!/bin/bash в начале скрипта? Вот, например, здесь работает http://wiki.ubuntuusers.de/_attachment?target=Skripte%2FSplitten+und+Vereinig... Там используется другой способ, без while read переменная $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS заносится в массив, а потом идет обращение к элементам массива.

Если это не поможет, сообщите используемый дистрибутив и версию bash?

>А вообще, причём здесь экспорт?

Да ни причём, может это бы заставило вас перечитать man bash.

mky ★★★★★
()
Ответ на: комментарий от mky

>> Не знаю, почему у вас не работает.

Потому что с массивом надо было работать, а Вы сразу не сказали :))
Вот так всё работает:

temp=$IFS
IFS=$'\n'
arrFILES=($(echo "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"))
IFS=$temp

for line in "${arrFILES[@]}"; do
    zenity --info --text="$line" --title='Передан файл:'
done

Спасибо!

The_gray_Cardinal
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.