Вопрос по bash – Проблемы с одинарными кавычками в скрипте bash

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 (включая одинарные кавычки в команде).

Спасибо!

@glennjackman Вам определенно нужны цитаты. Запуск без кавычек ничего не дает. Я не могу это объяснить, но я попробовал это. Jeff Erickson
Я скептически отношусь к тому, что выneed одинарные кавычки. Когда вы запускаете эту команду из оболочки, оболочка потребляет их и передает одинunquoted слово для команды R. glenn jackman
@GordonDavisson Решение обратной косой черты, которое вы описали, сработало! Спасибо! Это было идеально, потому что проблема, казалось, заключалась в том, действительно ли кавычки - или что-то комбинация одинарных и двойных кавычек - фактически являлись частью выполняемой команды. Если вы напишите свой ответ как официальный ответ, я приму его. Еще раз спасибо. Jeff Erickson
Я согласен с @glenn Jackman; вам могут понадобиться какие-то кавычки, но смысл кавычек состоит в том, чтобы изменить способ, которым оболочка анализирует свое содержимое - они невидимы для самой программы. Например,somecmd '--args part1 part2 part3' запускает somecmd с теми же аргументами, что иsomecmd "--args part1 part2 part3" а такжеsomecmd --args' 'part1' 'part2' 'part3' а такжеsomecmd --args\ part1\ part2\ part3, Во всех этих случаях то, что делают кавычки / экранирование, - это заставляет оболочку обрабатывать пробелы как часть одного аргумента, а не как разделители между аргументами. Gordon Davisson

Ваш Ответ

4   ответа
1

(двойную кавычку) или закрывать & apos; с & apos; то есть

#!/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

Или если вам нужноargs ... снова в одиночной цитате, то просто напиши

#!/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
Error: User Rate Limit Exceeded
1

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Jeff Erickson
Error: User Rate Limit Exceeded Jeff Erickson
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

Проблема заключается в том, что хотя одинарные кавычки подавляют особое значение пробелов (как вы хотите), они также подавляют особое значение$s (что вы не хотите). Так что вам нужно что-то более избирательное. Одним из вариантов было бы процитировать / убежать пробелы, но оставить$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.

0

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

Error: User Rate Limit Exceeded Jeff Erickson
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededset -xError: User Rate Limit Exceeded++ R CMD BATCH --no-save --no-restore --slave ' '\''--args 2 Vocab May12'\'' ' tabulate.r /dev/tty Jeff Erickson

Похожие вопросы