Bash: пробел в значении переменной, позже используемый как параметр - PullRequest
6 голосов
/ 12 февраля 2010

Во время написания bash-скрипта, помогающего создавать миниатюры поляроидов с помощью команды convert Imagick. Я столкнулся с проблемой. Хотя мне удается обойти это (на самом деле, поскольку convert достаточно гибок), я все еще хочу знать, как решить эту проблему без такого конкретного обходного пути.

Таким образом, скрипт bash получит значение заголовка, которое может содержать пробел. Я хочу использовать эту подпись в качестве параметра convert. Если заголовок пустой (''), я не буду использовать опцию '-caption' для команды convert. Как это:

CAPTION="Is this Cute?" # The actual value will be tacked from the parameter of this bash.
IN_FILE="resources/puppy.png"
OUTFILE="resources/puppy_polaroid.png"

# If CAPTION is not empty, reformat CAPTION
if [ "$CAPTION" != "" ]; then CAPTION="-caption \"$CAPTION\""; fi
# otherwise, do not use '-caption' add all

COMMAND="convert $CAPTION \"$IN_FILE\" \"$OUTFILE\""
echo "Command: $COMMAND" #This echo a value command
`$COMMAND`

echo повторяет команду value, которую можно скопировать, можно вставить в терминал и запустить. НО bash не работает. Как я могу это сделать?

ПРИМЕЧАНИЕ: В случае convert, -caption "" выполняет работу. Я знаю это и в настоящее время использую это как обходной путь.

Заранее спасибо за помощь.

РЕДАКТИРОВАТЬ: Из ответа вот код, который работает для меня сейчас.

... # Get CAPTION and GRAVITY from parameters

if [ "$CAPTION" != "" ]; then ARGS_CAPTION=(-caption "$CAPTION"); fi
if [ "$GRAVITY" != "" ]; then ARGS_GRAVITY=(-gravity "$GRAVITY"); fi

if [ ! -f "$IN_FILE"  ]; then echo "The input file does not exist: '$IN_FILE'"; exit; fi
if [ "$OUTFILE" == "" ]; then OUTFILE=${IN_FILE%.*}-${IN_FILE#*.}-polaroid.png; fi

ARGS=("${ARGS_CAPTION[@]}" -thumbnail 480x480 -border 5x5 -pointsize 60 "${ARGS_GRAVITY[@]}" +polaroid -thumbnail 120x120)
echo convert "${ARGS[@]}" "$IN_FILE" "$OUTFILE";
convert "${ARGS[@]}" "$IN_FILE" "$OUTFILE"

Я надеюсь, что это будет полезно для тех, кто ищет подобное решение.

Ответы [ 4 ]

10 голосов
/ 12 февраля 2010

Вы хотите прочитать запись 050 в BASH FAQ :

Я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!

Переменные содержат данные. Функции содержат код. Не помещайте код в переменные! Есть много ситуаций, в которых люди пытаются вставить команды или аргументы команд в переменные, а затем запустить их. Каждый случай должен рассматриваться отдельно.

...

  1. Я создаю команду на основе информации, известной только во время выполнения

Корень проблемы, описанной выше, заключается в том, что вам нужен способ сохранить каждый аргумент как отдельное слово, даже если этот аргумент содержит пробелы. Кавычки не сделают это, но массив будет. (Мы видели это в предыдущем разделе, где мы создали массив addrs на лету.)

Если вам нужно создать команду динамически, поместите каждый аргумент в отдельный элемент массива. Оболочка с массивами (например, Bash) делает это намного проще. POSIX sh не имеет массивов, поэтому самое близкое, что вы можете получить, - это создать список элементов в позиционных параметрах. Вот POSIX-версия функции sendto из предыдущего раздела:

2 голосов
/ 12 февраля 2010

Использовать массив, например:

#!/bin/bash
# ^^^ - note the shebang line explicitly using bash, not /bin/sh

CAPTION="Is this Cute?" # The actual value will be tacked from the parameter of this bash.
IN_FILE="resources/puppy.png"
OUTFILE="resources/puppy_polaroid.png"

extra_args=( )
if [[ $CAPTION ]] ; then
  extra_args+=( -caption "$1" )
fi
convert "${extra_args[@]}" "$INFILE" "$OUTFILE"

Эта конструкция предполагает, что вы потенциально собираетесь добавлять множество дополнительных аргументов. Обратите внимание, что += не поддерживается в некоторых старых версиях bash, которые все еще присутствуют в системах, развернутых в полевых условиях (особенно RHEL4). Для таких старых выпусков может потребоваться написать extra_args=( "${extra_args[@]}" -caption "$1" ) для добавления в массив.

1 голос
/ 12 февраля 2010

Если в последней строке ставить галочку в конце $COMMAND, сценарий попытается выполнить вывод команды, а не саму команду.

$ c='echo hi'
$ `$c`
hi: command not found

Это будет работать:

if [[ "$CAPTION" != "" ]]
then
    convert -caption "$CAPTION" "$IN_FILE" "$OUTFILE"
else
    convert "$IN_FILE" "$OUTFILE"
fi
0 голосов
/ 12 февраля 2010
CAPTION="$1"
IN_FILE="resources/puppy.png"
OUTFILE="resources/puppy_polaroid.png"

case "$CAPTION" in
  "" ) CAPTION="-caption ''";;
  * ) CAPTION='-caption "$CAPTION"';;
esac

convert $CAPTION "$IN_FILE" "$OUTFILE"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...