簡體   English   中英

在bash腳本中擴展變量時如何保留包含空格的單詞?

[英]How preserve words containing spaces while expanding variables in bash script?

我的方案如下:

我有一個 shell 腳本,它執行一個調用 C 程序的命令:

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

其中 name 是一個帶有空格的字符串 sa "String With Spaces"從另一個 python 腳本傳遞給 shell。

我的問題是,當我在 C 中讀取該參數時,它作為多個參數而不是一個參數傳遞。 我試過$@$*和所有這些東西。 我還嘗試在 C 中創建一個函數,將StringWithSpaces的幾個argv[i] StringWithSpaces ,但我有點卡住了。 我希望我可以將 C 中的變量作為單個參數讀取,以使程序盡可能簡單。

這是確切的外殼代碼(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

將命令放入一個數組中:

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 ,該命令引用其參數,以向用戶顯示正確的引用。 但這是審美或用戶界面的選擇; 它不會影響執行的命令。

我的問題是,當我在 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"

cc

#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 中以進行 echo 然后執行它,您可以執行以下操作:

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'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM