Цитирование в присваивании переменной bash - PullRequest
2 голосов
/ 08 сентября 2010

Использование следующего упрощенного извлечения кода:

DIR='a b'
mount_command="./mount.cpfs $loop $DIR -f $OPTS"
sudo $mount_command

Выполняет эту строку при включенной трассировке:

+ sudo ./mount.cpfs /dev/loop0 a b -f -o default_permissions,allow_other,attr_timeout=0

Но DIR не заключено в кавычки, поэтому a иb передаются как разные параметры, а не как один и тот же ./mount.cpfs.

Каков наилучший способ создать последовательность команд, подобную этой, и затем развернуть ее в более позднюю командную строку?

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

Пример использования mount_command

mount_command="./mount.cpfs $loop $DIR -f $OPTS"
case "$MODE" in
    gdb)
        sudo gdb -return-child-result -x gdbbatch \
            --args $mount_command
        ;;
    normal)
        sudo $mount_command
        ;;
    valgrind)
        sudo valgrind --track-fds=yes --leak-check=full --malloc-fill=0x80 \
            --free-fill=0xff $mount_command
        ;;
    *)
        echo "Mode '$MODE' unknown"
        mounted=''
        exit 2
        ;;
esac

Update0

Пожалуйста, проверьте ваши предложения, я не думаю, что решение является простым.

Ответы [ 4 ]

5 голосов
/ 08 сентября 2010

Лучший способ в bash - использовать массив. В массиве будут храниться слова, предназначенные для разделения, и пробелы внутри отдельных слов:

DIR='a b'
mount_command=(./mount.cpfs $loop "$DIR" -f $OPTS)
sudo "${mount_command[@]}"

Когда "${mount_command[@]}" раскрывается, каждый элемент раскрывается как один аргумент до sudo, даже если у него есть пробелы.

Обратите внимание, как я цитировал "$DIR", но не $OPTS, поскольку ваш $OPTS содержит несколько слов, предназначенных для передачи в команду монтирования в виде отдельных слов, но $DIR следует хранить вместе. Однако вы можете сделать OPTS массивом так же, как mount_command, и развернуть его в определении mount_command как "${OPTS[@]}":

DIR='a b'
OPTS=(-o default_permissions,allow_other,attr_timeout=0)
mount_command=(./mount.cpfs $loop "$DIR" -f "${OPTS[@]}")
sudo "${mount_command[@])"

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

1 голос
/ 08 сентября 2010

Попробуйте использовать eval .

Учитывая следующий скрипт, называемый test :

#!/bin/bash
# test

echo $1

Если я сделаю это:

DIR='a b'
CMD=."/test \"$DIR\""
eval $CMD

выводит

a b

См. этот вопрос

0 голосов
/ 11 октября 2012
DIR='a b'
OPTS='-o allow_other,attr_timeout=0'
mount_command="./mount.cpfs '$loop' '$DIR' -f '$OPTS'"
eval sudo $mount_command

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

В вашем случае вам нужно заключить в кавычки переменную '$ DIR' (а лучше все, что может содержать пробелы). Это понятно Но оболочка интерпретирует строки только один раз! Вы должны поручить это переинтерпретировать с помощью команды eval . Без eval переменная $ mount_command равна расширен, но цитирование внутри не обрабатывается.

Вы можете прочитать мою короткую статью об этом: Белая ракушка

0 голосов
/ 08 сентября 2010

Попробуйте

mount_command="./mount.cpfs $loop \"$DIR\" -f $OPTS"

Попробуйте вместо этого:

DIR='a b'
#following line replaces space occurrences with "\ "
DIR=`echo $DIR | replace ' ' '\ '`
mount_command="./mount.cpfs $loop $DIR -f $OPTS"
sudo $mount_command
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...