2012-05-17 2 views
2

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

#!/bin/bash 

if [ "$2" == "PracSci" ]; 
then 
    echo "Running tabulate.science.r" 
    R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.science.r /dev/tty 
else 
    echo "Running tabulate.r" 
    R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty 
fi 

При запуске в ./script.sh 2 Vocab May12, например, сама команда выполняется без значений переменных.

Как я могу расширить переменные, все еще получая команду для запуска?

Для того чтобы быть ясным, команда, которую я пытаюсь запустить, это: R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty (включая одинарные кавычки в команде).

Спасибо!

+1

Я скептически отношусь к тому, что вам нужны * одиночные кавычки. Когда вы запускаете эту команду из оболочки, оболочка потребляет их и передает одно слово ** без кавычек ** команде R. –

+0

@glennjackman Вам обязательно нужны кавычки. Запуск без кавычек ничего не дает. Я не могу это объяснить, но я попробовал. –

+1

Я согласен с @glenn jackman; вам могут понадобиться кавычки какого-то типа, но точка кавычек заключается в изменении того, как оболочка анализирует его содержимое - они невидимы для самой программы. Например, 'somecmd '--args part1 part2 part3'' запускает somecmd с точно такими же аргументами, что и' somecmd' --args part1 part2 part3 "и' somecmd --args '' part1 '' part2 '' part3'' и 'somecmd --args \ part1 \ part2 \ part3'. Во всех этих случаях кавычки/escape-файлы делают оболочку обрабатывать пространства как часть одного аргумента, а не разделители между аргументами. –

ответ

4

Короткий ответ: используйте двойные кавычки вместо одиночных кавычек (как предложено @Pavel). И когда вы сомневаетесь, используйте set -x, чтобы узнать, как оболочка анализирует ваши команды.

Длинный ответ: кавычки не передаются команде; вместо этого они разбираются (и удаляются) оболочкой, прежде чем аргументы передаются команде. То, что они делают, - это изменить способ интерпретации оболочки внутри кавычек (как правило, путем подавления особых значений некоторых символов), что означает, что вам нужно выбрать соответствующие кавычки, чтобы разрешить специальные символы, которые вы хотите проанализировать, и подавить их вы должны рассматриваться как простые персонажи. Например, рассмотрим следующую команду:

R CMD BATCH --no-save --no-restore --slave '--args 2 Vocab May12' tabulate.r /dev/tty 

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

R CMD BATCH --no-save --no-restore --slave "--args 2 Vocab May12" tabulate.r /dev/tty 
R CMD BATCH --no-save --no-restore --slave --args' '2' 'Vocab' 'May12 tabulate.r /dev/tty 
R CMD BATCH --no-save --no-restore --slave --args\ 2\ Vocab\ May12 tabulate.r /dev/tty 

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

Теперь давайте рассмотрим команду, которая не работает для вас:

R CMD BATCH --no-save --no-restore --slave '--args $1 $2 $3' tabulate.r /dev/tty 

Проблема в том, что в то время как одиночные кавычки подавляют особый смысл пространств (как вы хотите), они также подавляет особый смысл $ (который вам не нужен). Поэтому вам нужно что-то более избирательное.Одним из вариантов было бы процитировать/избежать пробелов, но оставить $1 и т.д. неупомянута:

R CMD BATCH --no-save --no-restore --slave --args' '$1' '$2' '$3 tabulate.r /dev/tty 
R CMD BATCH --no-save --no-restore --slave --args\ $1\ $2\ $3 tabulate.r /dev/tty 

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

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

R CMD BATCH --no-save --no-restore --slave "--args $1 $2 $3" tabulate.r /dev/tty 

Двойные кавычки подавляющие особый смысл пространств (как вы хотите), позволяют $ вызвать расширение переменных (также, как вы хотите), НО не допускайте дальнейшего разбора после того, как переменные были расширены (также вероятно, что вы хотите). Пробелы или другие забавные символы в аргументах могут по-прежнему вызывать проблемы в сценарии R, но по крайней мере это мешает им создавать проблемы до того, как R-скрипт будет запущен.

1

использовать двойные кавычки - или я пропущу точку?

+0

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

+0

Тогда предложения Килиана Фота - это путь. Поместите «set -x» в начале вашего скрипта, чтобы увидеть, что происходит во время выполнения. – Pavel

+0

Я попробовал его предложение, пожалуйста, см. Мою оценку на его пост для вывода. –

1

вы можете использовать «(двойные кавычки) вместо или закрытия„с“т

#!/bin/bash 

if [ "$2" == "PracSci" ]; 
then 
    echo "Running tabulate.science.r" 
    R CMD BATCH --no-save --no-restore --slave '--args '$1' '$2' '$3 tabulate.science.r /dev/tty 
else 
    echo "Running tabulate.r" 
    R CMD BATCH --no-save --no-restore --slave '--args '$1' '$2' '$3 tabulate.r /dev/tty 
fi 

Или, если вам нужно арг ... в одинарной кавычки снова, то просто написать

#!/bin/bash 

if [ "$2" == "PracSci" ]; 
then 
    echo "Running tabulate.science.r" 
    R CMD BATCH --no-save --no-restore --slave "'--args $1 $2 $3'" tabulate.science.r /dev/tty 
else 
    echo "Running tabulate.r" 
    R CMD BATCH --no-save --no-restore --slave "'--args $1 $2 $3'" tabulate.r /dev/tty 
fi 
+0

Очистить сеанс отладки. – casperOne

0

Если вы правильно поняли, вы хотите " '--args $1 $2 $3' " вместо обычного '--args $1 $2 $3'. Поскольку токен верхнего уровня представляет собой строку с двойными кавычками, переменные будут расширены, а ' останется в токене, а также в том, что R может использовать им.

+1

Возможно, нет; с одинарными кавычками внутри двойных кавычек, дочерний процесс (возможно) увидит одиночные кавычки, что, вероятно, не является тем, что требуется. Замена одиночных кавычек двойными кавычками будет работать. –

+0

Ни одно из этих предложений не работает. Оба они вызывают эхо, а затем скрипт заканчивается без каких-либо действий с помощью команды R. –

+0

Использование 'set -x', выход для этой строки с использованием вашего предложения:' ++ R CMD BATCH --no-save --no-restore --slave '' \ '' - args 2 Vocab May12 '\ '' 'tabulate.r/dev/tty' –

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