2009-10-12 3 views
7

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

Короче говоря, я хочу, чтобы выполнить команду следующей структуры через сценарий оболочки Bash: command_name -a -b arg1 arg2 -c «арг с непечатаемыми здесь»

Но независимо от того, как я стараюсь, то пробелы не сохраняются в строке и по умолчанию отмечены. Решение пожалуйста,

редактировать: Это главная часть моего сценария:

#!/bin/bash 

#-------- BLACKRAY CONFIG ---------------# 
# Make sure the current user is in the sudoers list 
# Running all instances with sudo 

BLACKRAY_BIN_PATH='/opt/blackray/bin' 
BLACKRAY_LOADER_DEF_PATH='/home/crozzfire' 
BLACKRAY_LOADER_DEF_NAME='load.xml' 
BLACKRAY_CSV_PATH='/home/crozzfire' 
BLACKRAY_END_POINT='default -p 8890' 
OUT_FILE='/tmp/out.log' 

echo "The current binary path is $BLACKRAY_BIN_PATH" 


# Starting the blackray 0.9.0 server 
sudo "$BLACKRAY_BIN_PATH/blackray_start" 

# Starting the blackray loader utility 
BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "\"$BLACKRAY_END_POINT\""" 

sudo time $BLACKRAY_INDEX_CMD -a $OUT_FILE 

#--------- END BLACKRAY CONFIG ---------# 
+0

Извините, но вы предоставили слишком мало информации. Какую оболочку вы используете (bash, ksh, csh, ...)? Можете ли вы сказать, какую команду вы пытаетесь выполнить? Если это стандартная утилита UNIX, можете ли вы сказать ее версию? –

+0

скрипт bash. Хорошо, вот что я пытаюсь сделать: .... BLACKRAY_END_POINT = "по умолчанию -p 8890" .... CMD = "$ BLACKRAY_BIN_PATH/blackray_loader -c $ BLACKRAY_LOADER_DEF_PATH/$ BLACKRAY_LOADER_DEF_NAME -d $ BLACKRAY_CSV_PATH - e \ "$ BLACKRAY_END_POINT \" " ... Теперь я хочу выполнить указанную выше команду таким образом, чтобы $ BLACKRAY_END_POINT обрабатывался как одна строка и не получил токенизацию. $ BLACKRAY_END_POINT - это строка, содержащая пробелы, а bash разбивает ее на разные слова. Я хочу сохранить пробелы и передать всю строку в виде одного аргумента. – crozzfire

+0

Неизвестно, встретить обратную косую черту-двойную кавычку (\ ") .Краса обратной косой черты, встречаться неизвестно. –

ответ

1

вероятно, вы должны окружить аргумент в двойные кавычки (например, «$ {6}»).

После OP комментарий оно должно быть "$ BLACKRAY_END_POINT"

+0

Пробовал. Но он по-прежнему занимает только« по умолчанию », а не всю строку :( – crozzfire

+0

Заменить -e \" $ BLACKRAY_END_POINT \ «" до "\" $ BLACKRAY_END_POINT \ "". Вам нужно "", чтобы избежать пробелов в вашем скрипте и дополнительных \ "\", чтобы избежать пробелов, когда команда выполнена – dimba

+0

по-прежнему не повезло, требуется -> "по умолчанию, поскольку arg now (дополнительные открытые кавычки). Для запуска я использую: sudo time $ CMD -a $ OUT_FILE. Если я заменю $ CMD на «$ CMD», он не даст мне такой ошибки файла или каталога. – crozzfire

1

Edit:

Try:

BLACKRAY_END_POINT="'default -p 8890'" 

или

BLACKRAY_END_POINT='"default -p 8890"' 

или

BLACKRAY_END_POINT="default\ -p\ 8890" 

или

BLACKRAY_END_POINT='default\ -p\ 8890' 

и

BLACKRAY_INDEX_CMD="$BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e $BLACKRAY_END_POINT" 

Оригинальный ответ:

Является ли blackray_loader сценарий оболочки?

Вот доказательство того, что вам приходится иметь дело с этим вопросом, как при указании параметра и при обращении с ним:

текстовый файл с именем «test.txt» (в том числе номера строк):

1 two words 
2 two  words 
3 two 
4 words 

сценарий под названием "spacetest":

#!/bin/bash 
echo "No quotes in script" 
echo $1 
grep $1 test.txt 
echo 

echo "With quotes in script" 
echo "$1" 
grep "$1" test.txt 
echo 

Запуск его ./spacetest "two--------words" (замените дефисы с пробелами):

No quotes in script 
two words 
grep: words: No such file or directory 
test.txt:1 two words 
test.txt:2 two  words 
test.txt:3 two 

With quotes in script 
two  words 
2 two  words 

Вы можете видеть, что в разделе «без кавычек» он пытался сделать grep two words test.txt, которые интерпретированы «слова» в качестве имени файла в дополнение к «test.txt». Кроме того, echo сбросил лишние пробелы.

Когда параметр указан, как и во втором разделе, grep видел его как один аргумент (включая дополнительные пробелы) и обрабатывал его правильно. И echo сохранили дополнительные пробелы.

Я использовал дополнительные пробелы, между прочим, просто чтобы помочь в демонстрации.

+0

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

+0

Это именно то, что я демонстрирую. В приведенном выше скрипте 'grep' является резервным для вашего' blackray_loader'. Ваша команда должна будет правильно обрабатывать параметры. Однако см. Редактирование для другой вещи, чтобы попробовать. –

5

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

sudo time $BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT" -a $OUT_FILE 

Если вам действительно нужно, чтобы сохранить команду и использовать его в дальнейшем, есть несколько вариантов; у bash-hackers.org wiki есть good page on the subject. Она смотрит на меня, как самый полезный здесь, чтобы поместить команду в массив, а не простой переменной:

BLACKRAY_INDEX_CMD=($BLACKRAY_BIN_PATH/blackray_loader -c $BLACKRAY_LOADER_DEF_PATH/$BLACKRAY_LOADER_DEF_NAME -d $BLACKRAY_CSV_PATH -e "$BLACKRAY_END_POINT") 

sudo time "${BLACKRAY_INDEX_CMD[@]}" -a $OUT_FILE 

Это позволяет избежать вся путаница между пространствами-разделительные-слов и пространства-внутри-слова, потому что слова не разделены пробелами - они находятся в отдельных элементах массива. Расширение массива в двойных кавычках с помощью суффикса [@] сохраняет эту структуру.

(кстати, еще один вариант будет использовать кавычки экранированы, а как вы делаете, а затем запустить команду с eval Не делайте этого,.. Это хороший способ ввести странные ошибки синтаксического анализа)

3

у меня есть предложение:

# iterate through the passed arguments, save them to new properly quoted ARGS string 
while [ -n "$1" ]; do 
    ARGS="$ARGS '$1'" 
    shift 
done 

# invoke the command with properly quoted arguments 
my_command $ARGS 
+3

Это не работает вообще - оболочка анализирует кавычки перед расширением переменных, поэтому, если в значениях переменных есть кавычки, они не рассматриваются как кавычки, а просто обычные символы. В принципе, для них слишком поздно, чтобы иметь предполагаемый эффект. Что на самом деле происходит, так это то, что они передаются команде в качестве части аргумента, чего вы не хотите. –

-1

пост на другом блоге спас меня для этого пробельной проблемы: http://logbuffer.wordpress.com/2010/09/23/bash-scripting-preserve-whitespaces-in-variables/

по умолчанию пробельных символов являются trimed:

«Причиной такого поведения является внутренняя переменная оболочки $ IFS (внутренний разделитель полей), по умолчанию это пробел, табуляция и новая строка. Чтобы сохранить все смежные пробельные вы должны установить ИФС на что-то другое "

С МФС байпас:

bash> IFS='%' 
bash> echo $VAR1 
abc  def gh ijk 
bash>unset IFS 
bash> 

Это прекрасно работает для моей команды дела:

su - user1 -c 'test -r "'${filepath}'"; ....' 

Надеюсь, что это поможет.

+0

Остановите распространение запаздывающих хаков, пожалуйста. Вы ясно показываете, что не понимаете важность цитат. По умолчанию, пробелы: trimed_: WRONG. Без кавычек вы переходите к разделению слов и расширению имен файлов. Вылечите это с помощью кавычек: 'VAR1 =" abc def gh ijk "; echo "$ VAR1" '. Теперь это работает. Кроме того, как бы вы объяснили, что происходит в случае шаблона: 'VAR1 = '*'; echo $ VAR1' vs 'VAR1 = '*'; echo "$ VAR1" '? Даже с вашей линией 'IFS' вы получите тот же ужасный результат:' IFS =%; VAR1 = '*'; echo $ VAR1'. Просто используйте больше кавычек. Период. –

+0

Можете ли вы объяснить мне, почему в этом случае обрезается путь к файлу: 'test -r' '$ {filepath}' "'? – Kloe2378231

+0

Вы должны понять, как работают кавычки. Для кавычек нет гнезд. Я возьму вашу полную команду: 'su - user1 -c 'test -r"' $ {filepath} '";''. Если 'filepath' содержит пробелы, например' filepath = 'a b'', тогда, когда вы выполняете 'su - user1 -c' test -r '' $ {filepath} '";' ', bash будет расширяться до следующего слова: 'su',' -', 'user1',' -c', 'test -r" a', 'b"; '. Не то, что вы хотите. С 'IFS =%' it_seems_, что он работает, но он будет терпеть неудачу, если 'filepath' содержит подстановочные знаки или символ'% 'или символ' '' (или другие глобусы). –

0

Ниже мой пример le перезапуска скрипта через exec su USER или exec su - USER. Он вмещает:

  • вызывается из относительного пути или текущего рабочего каталога
  • пространства в имени сценария и аргументы
  • одно- и двойные кавычки в аргументах, без безумных побегов, как: \\»

# 
# This script should always be run-as a specific user 
# 
user=jimbob 
if [ $(whoami) != "$user" ]; then 
    exec su -c "'$(readlink -f "$0")' $(printf " %q" "[email protected]")" - $user 
    exit $? 
fi 
Смежные вопросы