在bash中将带空格的字符串作为函数参数传递


173

我正在编写一个bash脚本,我需要在其中将包含空格的字符串传递给bash脚本中的函数。

例如:

#!/bin/bash

myFunction
{
    echo $1
    echo $2
    echo $3
}

myFunction "firstString" "second string with spaces" "thirdString"

运行时,我期望的输出是:

firstString
second string with spaces
thirdString

但是,实际输出的是:

firstString
second
string

有没有一种方法可以将带有空格的字符串作为单个参数传递给bash中的函数?


对我有用...尽管“ function bla(){echo $ 1;}”,我不能对函数使用完整的语法,但不能将其中的一个简短化。不确定会有所不同。什么版本的bash?
尤金(Eugene)2009年

8
请尝试echo "$@"for i in "$@"; do echo $i ; done使用包含空格的正确引用的参数。这是本节所有bash文档中非常明确提及的positional parameters内容。
Samveen 2013年

1
我遇到了类似的问题,试图将一个带引号的字符串作为参数传递,并且仅将字符串的第一个单词识别为参数的一部分。Samveen的建议将$ 1更改为$ @为我工作。请注意,我只是将一个参数传递给函数,但是如果要使用for语句传递更多参数,则将是必需的。
艾琳·盖尔


1
尝试 myFunction "$@"
vimjet

Answers:


176

您应该加上引号,并且函数声明错误。

myFunction()
{
    echo "$1"
    echo "$2"
    echo "$3"
}

和其他人一样,它也对我有用。告诉我们您使用的Shell版本。


3
这对我也很好。如果我们在myFunction内调用另一个函数,则传递带有引号的参数。干杯:)
minhas14年

2
您能解释一下为什么需要引号吗?无论有没有,我都尝试过,但它对我没有用。我正在使用Ubuntu 14.04,GNU bash,版本4.3.11(1)-发行版(x86_64-pc-linux-gnu)。什么的工作对我来说使用$ @是(带或不带引号)。
凯尔·贝克

@KyleBaker,不带引号,$@就像未加引号一样$*-结果是字符串分割的,然后分别进行全球扩展,因此,如果您使用制表符,它们将转换为空格,如果您有可以被评估为全球表达式的单词,将会是,等等
查尔斯·达菲

17

解决上述问题的另一种方法是将每个字符串设置为一个变量,然后使用以文字美元符号表示的变量来调用该函数\$。然后在函数中使用eval读取变量并按预期输出。

#!/usr/bin/ksh

myFunction()
{
  eval string1="$1"
  eval string2="$2"
  eval string3="$3"

  echo "string1 = ${string1}"
  echo "string2 = ${string2}"
  echo "string3 = ${string3}"
}

var1="firstString"
var2="second string with spaces"
var3="thirdString"

myFunction "\${var1}" "\${var2}" "\${var3}"

exit 0

输出为:

    string1 = firstString
    string2 = second string with spaces
    string3 = thirdString

在尝试解决与此类似的问题时,我遇到了UNIX问题,认为我的变量是空间限定的。我试图将管道定界字符串传递给函数,该函数awk用于设置一系列变量,这些变量随后用于创建报告。最初,我尝试了ghostdog74发布的解决方案,但由于并非所有参数都都用引号引起来,因此无法使其正常工作。将双引号添加到每个参数后,它便开始按预期运行。

以下是我的代码的before状态,after状态可以正常运行。

之前-无效代码

#!/usr/bin/ksh

#*******************************************************************************
# Setup Function To Extract Each Field For The Error Report
#*******************************************************************************
getField(){
  detailedString="$1"
  fieldNumber=$2

  # Retrieves Column ${fieldNumber} From The Pipe Delimited ${detailedString} 
  #   And Strips Leading And Trailing Spaces
  echo ${detailedString} | awk -F '|' -v VAR=${fieldNumber} '{ print $VAR }' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

while read LINE
do
  var1="$LINE"

  # Below Does Not Work Since There Are Not Quotes Around The 3
  iputId=$(getField "${var1}" 3)
done<${someFile}

exit 0

售后服务代码

#!/usr/bin/ksh

#*******************************************************************************
# Setup Function To Extract Each Field For The Report
#*******************************************************************************
getField(){
  detailedString="$1"
  fieldNumber=$2

  # Retrieves Column ${fieldNumber} From The Pipe Delimited ${detailedString} 
  #   And Strips Leading And Trailing Spaces
  echo ${detailedString} | awk -F '|' -v VAR=${fieldNumber} '{ print $VAR }' | sed 's/^[ \t]*//;s/[ \t]*$//'
}

while read LINE
do
  var1="$LINE"

  # Below Now Works As There Are Quotes Around The 3
  iputId=$(getField "${var1}" "3")
done<${someFile}

exit 0

7

解决此问题的最简单方法是\"在运行Shell脚本时只需要使用空格分隔的参数:

#!/bin/bash
myFunction() {
  echo $1
  echo $2
  echo $3
}
myFunction "firstString" "\"Hello World\"" "thirdString"

5

您对myFunction的定义是错误的。它应该是:

myFunction()
{
    # same as before
}

要么:

function myFunction
{
    # same as before
}

无论如何,它看起来不错,并且在Bash 3.2.48上对我来说效果很好。


5

我迟了9年,但更有活力的方法是

function myFunction {
   for i in "$*"; do echo "$i"; done;
}

2
太好了!这正是我一段时间以来在许多问题上一直在寻找的东西。谢谢!
prosoitos

2

适用于我的简单解决方案-报价$ @

Test(){
   set -x
   grep "$@" /etc/hosts
   set +x
}
Test -i "3 rb"
+ grep -i '3 rb' /etc/hosts

我可以验证实际的grep命令(感谢设置-x)。


-1

如果将初始文本设置为字符串类型变量,则可以扩展此问题,例如:

function status(){    
  if [ $1 != "stopped" ]; then
     artist="ABC";
     track="CDE";
     album="DEF";
     status_message="The current track is $track at $album by $artist";
     echo $status_message;
     read_status $1 "$status_message";
  fi
}

function read_status(){
  if [ $1 != "playing" ]; then
    echo $2
  fi
}

在这种情况下,如果您不将status_message变量作为字符串传递(用“”包围),它将被拆分为一系列不同的参数。

“ $ variable”:当前轨道是ABC在DEF的CDE

$ variable


OP使用了myFunction "firstString" "second string with spaces" "thirdString"它,但对他不起作用。因此,您的建议不适用于此问题。
doubleDown 2013年

-2

遇到过同样的问题,实际上问题不是函数或函数调用,而是我作为参数传递给函数的问题。

该函数是从脚本主体“ main”中调用的,因此我从命令行传递了“ st1 a b”,“ st2 c d”,“ st3 e f”,并使用myFunction $ *将其传递给了函数

$ *会导致问题,因为它扩展为一组字符,这些字符将在使用空白作为定界符的函数调用中进行解释。

解决方案是将显式参数处理中对函数的调用从'main'更改为函数:然后该调用为myFunction“ $ 1”“ $ 2”“ $ 3”,它将保留字符串内的空格,因为引号将定界因此,如果参数可以包含空格,则应在所有函数调用中显式处理该参数。

由于这可能是长时间搜索问题的原因,因此最好不要使用$ *传递参数...

希望有一天某个地方某人能有所帮助...


正确的答案是"$@",不是所有的报价"$1""$2"...位置paramters也没有$*
Samveen 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.