Bash: передача параметров в программу C через переменную оболочки. Как бороться с пробелами и цитированием символов? - PullRequest
0 голосов
/ 25 января 2020

My Bash script отправляет набор (несколько) параметров в программу C.

Это мой C программа :

$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char **argv )
{

    printf("Parameter 1 is: %s \n", argv[1]);
    printf("Parameter 2 is: %s \n", argv[2]);
    return 0;
}

После компиляции (как MyCProgram) она ведет себя нормально:

MyCProgram -f "/path/to/file/with spaces"
Parameter 1 is: -f
Parameter 2 is: /path/to/file/with spaces

Но при попытке отправить ей параметры через оболочку переменная :

$ var='-f "/path/to/file/with spaces" '
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: "/path/to/file/with
$ MyCProgram "$var"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram '$var'
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram "$(echo $var)"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo "$var")"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo '$var')"
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram '$(echo "$var")'
Parameter 1 is: $(echo "$var")
Parameter 2 is: (null)
$ var="-f '/path/to/file/with spaces' "
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: '/path/to/file/with

Как мне получить правильное поведение , это так же, как при запуске без переменных оболочки?

Примечания :

После Крейг Эстей ответ , это прекрасно работает:

$ var=(-f "/file with spaces")
$ MyCProgram "${var[@]}"

Этот метод работает, но только если я вручную (явно) присваиваю значение var. Предполагая, что var уже назначен (т. Е. Через чтение входных данных или чтение файлов), я бы сказал, что проблема здесь заключается в переносе его в переменную массива bash. Итак:

$ var='-f "/file with spaces"'
$ var2=( $var )
$ MyCProgram "${var2[@]}"
Parameter 1 is: -f
Parameter 2 is: "/file

Проблема все еще существует.

Ответы [ 4 ]

3 голосов
/ 25 января 2020

var='-f "/path/to/file/with spaces" '

В этой ситуации содержимое var является синтаксисом оболочки.

Для обработки синтаксиса оболочки мы можем поэтому использовать eval function:

eval "MyProgram $var"

Это создаст аргумент

MyProgram -f "/path/to/file/with spaces" 

, а затем оценит его как небольшой сценарий оболочки.

Нет необходимости говорить, что это может повлиять на безопасность , Мы доверяем входным данным, которые пошли на создание сценария, содержащегося в var. По этой причине eval следует избегать, насколько это возможно.

Когда мы вводим eval, мы должны подумать: кто контролирует входные данные, которые go в строку, передаваемую в eval? Может ли кто-нибудь злонамеренно проникнуть во что-то, чтобы заставить eval выполнить произвольный код?

Если конструкция var находится под вашим контролем и либо не имеет ненадежных входов, либо эти входы обрабатываются должным образом, то это может быть подходящим решением.

3 голосов
/ 25 января 2020

Без указания разделителя в xargs он анализирует кавычки и обратные слэши " и ', поэтому при условии, что содержимое var нормальное, вы можете сделать:

<<<"$var" xargs MyProgram

Вы можете написать свой собственный токенизатор для var контента - напр. разделите его на первый пробел, а затем удалите кавычки ".

# split var on space
IFS=' ' read -r option file <<<"$var"
# remove quotes from file - ie. remove last and first character
file=${file%\"}
file=${file#\"}
# run your program
MyProgram "$option" "$file"
3 голосов
/ 25 января 2020

Возможно, вы захотите использовать bash массив переменную

Чтобы установить переменную, выполните следующие действия:

var=(-f "/file with spaces")

Затем вызовите вашу программу:

MyCProgram "${var[@]}"
1 голос
/ 26 января 2020

Не могли бы вы попробовать следующее:

var='-f "/path/to/file/with spaces" '
declare -a var2="( $var )"
./MyCProgram "${var2[@]}"

Вывод:

Parameter 1 is: -f 
Parameter 2 is: /path/to/file/with spaces 

Обратите внимание, что declare может иметь потенциальный риск как eval, и вам необходимо принять элемент управления, чтобы произвольная строка не передавалась в declare.

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