如何在bash脚本中扩展变量的同时保留包含空格的单词?

时间:2019-01-30 09:33:30

标签: bash shell arguments

我的方案如下:

我有一个shell脚本,该脚本执行一个调用C程序的命令:

name=$1
StringWithSpaces=$name
command="someprogram.out $StringWithSpaces $otherarguments"
$command

其中name是一个带有空格s.a的字符串。 "String With Spaces"从另一个python脚本传递到外壳。

我的问题是,当我在C语言中读取该参数时,它作为多个参数而不是一个参数传递。我已经尝试过$@$*和所有其他东西。我也尝试过用C编写一个将argv[i]中的几个StringWithSpaces分开的函数,但是我有点卡住了。我希望我可以将C中的变量作为一个参数读取,以使程序尽可能简单。

这是确切的shell代码(bash):

#!/bin/bash

#$1 Nombre de la base de datos
#$2 $3 gps coordinates
#$4 geoDistance (radio en km)
#$5 imDownload (a 0: solo se descargan GPS, a 1 también imágenes y tags)
#$Disabled keywords (opcional, lista de keywords separados por comas) 

#Generamos el base path
BASE_DIR=`pwd`
#BASE_DIR=${BASE_DIR%/*}
EXE_DIR=$BASE_DIR/FlickrAPI/bin
DB_PATH=$BASE_DIR/data

#Exportamos las librerías, necesario para que funcione el código
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${BASE_DIR}/FlickrAPI/lib

cont=1;

#General DB
name=$1
gps="$2 $3"
geoDistance=$4
numImagesDB=3751
ncores=400;
imDownload=$5

dbDir=$DB_PATH/$name
mkdir "$dbDir";

rm -rf "$dbDir"/imagesDB
rm -rf "$dbDir"/tagsDB
rm -rf "$dbDir"/gps.txt

mkdir "$dbDir"/imagesDB
mkdir "$dbDir"/tagsDB
#tidx=`seq 7 $#`;
#keywords="";
#for ((i=7;i<=$#;i++))
#do
#  keywords=$keywords" "${!i};
#done
keywords=$6;
export LD_LIBRARY_PATH=/home/user/anaconda2/lib/
command="$EXE_DIR/get_GPS_bimestral $dbDir $gps z $numImagesDB $ncores $geoDistance $imDownload $keywords"
echo $command
$command

2 个答案:

答案 0 :(得分:0)

  

我的问题是,当我在C语言中读取该参数时,它将作为多个参数而不是仅作为一个参数传递。

在脚本中替换

command="$EXE_DIR/get_GPS_bimestral $dbDir $gps z $numImagesDB $ncores $geoDistance $imDownload $keywords"
echo $command
$command

作者

command="$EXE_DIR/get_GPS_bimestral \"$dbDir $gps z $numImagesDB $ncores $geoDistance $imDownload $keywords\""
echo $command
echo $command | bash

说明:

如果shell脚本 b 是:

./a.out "$* 3 4"

c.c

#include <stdio.h>

int main(int argc, char ** argv)
{
  printf("argc = %d, argv[1] = '%s'\n", argc, argv[1]);
}

然后:

pi@raspberrypi:/tmp $ ./b 1 2
argc = 2, argv[1] = '1 2 3 4'

C程序只接收一个arg,没关系

但是如果将脚本修改为例如:

command="./a.out \"$* 3 4\""
echo $command
$command

不起作用:

pi@raspberrypi:/tmp $ ./b 1 2
./a.out "1 2 3 4"
argc = 5, argv[1] = '"1'

因此,如果您想存储在var中以回显然后执行它,则可以执行以下操作:

command="./a.out \"$* 3 4\""
echo $command
echo $command | bash

执行:

pi@raspberrypi:/tmp $ ./b 1 2
./a.out "1 2 3 4"
argc = 2, argv[1] = '1 2 3 4'

当然,如果您希望将例如4作为单独的参数接收,只需将其放在字符串之外:

command="./a.out \"$* 3\" 4"
echo $command
echo $command | bash

执行:

pi@raspberrypi:/tmp $ ./b 1 2
./a.out "1 2 3" 4
argc = 3, argv[1] = '1 2 3'

答案 1 :(得分:0)

使用以下命令将命令放入数组中

Command=(someprogram.out "$StringWithSpaces" "$otherarguments")

@所示,使用"${Command[@]}"来扩展数组的引号来请求其所有成员时,bash会将其数组成员扩展为单个单词。因此,带有空格的所需字符串将保留为单个字符串。

这是一个示例脚本:

#!/bin/bash -e

function ShowArguments()
{
    for argument in "$@"; do
        echo "Argument:  $argument"
    done
}

Argument1="abc def"
Argument2="pdq xyz"

Command=(ShowArguments "$Argument1" "$Argument2")

echo "${Command[@]}"
"${Command[@]}"

上面的输出是:

ShowArguments abc def pdq xyz
Argument:  abc def
Argument:  pdq xyz

您可能希望"$otherarguments"$otherarguments。或者,如果它包含一个带有空格的字符串,应将其保留为字符串,则应使用用引号${otherarguments[@]}进行扩展的数组来处理它。这是一个引用用于保留参数的变量之一的示例:

#!/bin/bash -e

function ShowArguments()
{
    for argument in "$@"; do
        echo "Argument:  $argument"
    done
}

Argument1="Single argument with multiple words"
Argument2=("Multiple argument" with various "numbers of words")

Command=(ShowArguments "$Argument1" "${Argument2[@]}")

echo "${Command[@]}"
"${Command[@]}"

它产生:

ShowArguments Single argument with multiple words Multiple argument with various numbers of words
Argument:  Single argument with multiple words
Argument:  Multiple argument
Argument:  with
Argument:  various
Argument:  numbers of words

在那之后,您可能想用引人注目的自变量的更高级命令替换echo,以向用户显示正确的引号。但这是一种美观或用户界面选择;不会影响执行的命令。