bash — Невозможно передать разделенный пробелами аргумент из сценария оболочки в исполняемый файл C ++

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

Сценарий:

#!/bin/sh -h

MYARGS=""
for arg in "$@"; do
shift
case $arg in
*)
pattern=" "if [[ $arg =~ $pattern ]]; then
MYARGS="$MYARGS \"$arg\""else
MYARGS="$MYARGS $arg"fi
;;
esac
done
echo $MYARGS
./a.out $MYARGS

Программа:

#include "iostream"
int main (int argc, char *argv[])
{
for (int i = 0; i < argc; i++)
{
std::cout << argv[i] << std::endl;
}
}

Теперь я не хочу использовать $ @, поскольку мне нужно отфильтровать некоторые аргументы для передачи в основную программу.
Но, когда я пробую вышеупомянутую часть с разделенной пробелами строкой в ​​качестве аргумента, я получаю следующий вывод:

Command : ./a.out "a b"Output :
./a.out
a b

Command: a.sh "a b"Output :
"a b"./a.out
"a
b"

Проблема в том, что во втором случае аргументы автоматически разделяются, а «a» и «b» выступают в качестве разных аргументов, хотя я сохраняю кавычки «»

Что может быть решением этого?

3

Решение

Когда цитата попадает в переменную bash, это просто символ. Не путай то, что ты тип с тем, что содержит переменная. В этом отношении bash ничем не отличается от C.

const char* v = "a b";
printf("%s\n", v);    // => a b
const char* w = "\"a b\"";
printf("%s\n", w);    // => "a b"

Bash точно такой же:

$ v="a b"$ echo "$v"a b
$ w="\"a b\""$ echo "$w""a b"

Выше я поместил кавычки вокруг моих расширений переменных, которые вы должны всегда делать. (Ну, почти всегда. Но делайте это, если у вас нет действительно веской причины, и вы можете объяснить свою причину.)

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

Вы можете (и люди могут рекомендовать вам) использовать сложные конструкции, используя eval или Eval-подобные операции (как bash -c). Это почти всегда кончится горем. Самое простое, лучшее и рекомендуемое решение — использовать массив:

myargs=()

for arg in "$@"; do
shift
case "$arg" in
*) myargs+=("$arg") ;;
esac
done
echo "${myargs[@]}"./a.out "${myargs[@]}"

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

3

Другие решения

Просто используйте xargs

#!/bin/bash

MYARGS=""
for arg in "$@"; do
shift
case $arg in
*)
pattern=" "if [[ $arg =~ $pattern ]]; then
MYARGS="$MYARGS \"$arg\""else
MYARGS="$MYARGS $arg"fi
;;
esac
done
echo $MYARGS | xargs ./a.out
1

По вопросам рекламы [email protected]