スペースを含む文字列を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;}"は関数の完全な構文を使用しますが、短いものを1つのライナーにすることはできません。それが違いを生むかどうかはわかりません。bashのバージョンは何ですか?
ユージーン

8
試すecho "$@"か、for i in "$@"; do echo $i ; doneスペースを含む正しく引用されたパラメータを使用します。これは、セクションのすべてのbashドキュメントで非常に明確に述べられていますpositional parameters
Samveen 2013年

1
同様の問題があり、引用符で囲まれた1つの文字列をパラメーターとして渡し、文字列の最初の単語のみがパラメーターの一部として認識されていました。$ 1を$ @に変更するというSamveenの提案はうまくいきました。関数に渡すパラメーターは1つだけでしたが、forステートメントを使用してさらに渡す場合は、これが必要でした。
Erin Geyer


1
試してみる myFunction "$@"
vimjet 2017

回答:


176

引用符を付ける必要があります。また、関数宣言が間違っています。

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

そして、他の人のように、それも私のために働きます。使用しているシェルのバージョンを教えてください。


3
これは私にとっても非常にうまくいきます。myFunction内で別の関数を呼び出す場合は、引用符で引数を渡します。乾杯:)
minhas23

2
なぜ見積もりが必要なのか説明できますか?私は両方で試してみましたが、うまくいきませんでした。Ubuntu 14.04、GNU bash、バージョン4.3.11(1)-release(x86_64-pc-linux-gnu)を使用しています。何私のために働くことは$を使用して、@(または引用符なし)です。
カイルベイカー

@KyleBakerは引用符なしでは、引用符なしの$@ように動作します$*-結果は文字列分割され、個別にグロブ展開されるため、タブがある場合はスペースに変換され、グロブ式として評価できる単語がある場合はなどになります
Charles Duffy

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によって投稿されたソリューションを試しましたが、すべてのパラメーターが引用符で渡されていなかったため、それを機能させることができませんでした。各パラメーターに二重引用符を追加すると、期待どおりに機能し始めました。

以下は、私のコードの変更前の状態で、変更後の状態で完全に機能します。

変更前-機能しないコード

#!/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

この問題の最も簡単な解決策は\"、シェルスクリプトを実行するときに、スペースで区切られた引数を使用する必要があることです。

#!/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コマンドを確認できました(set -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 $ *を使用して関数に渡しました

$ *は、空白文字を区切り文字として使用する関数の呼び出しで解釈される一連の文字に展開されるため、問題を引き起こします。

解決策は、明示的な引数処理で関数の呼び出しを「メイン」から関数に変更することでした。呼び出しはmyFunction "$ 1" "$ 2" "$ 3"になり、引用符で区切られるため、文字列内の空白が保持されます。引数...したがって、パラメータにスペースを含めることができる場合は、関数のすべての呼び出しを通して明示的に処理する必要があります。

これが問題の長い検索の理由である可能性があるため、引数を渡すために$ *を使用しないことが賢明かもしれません...

これがいつかどこかで誰かを助けることを願っています... Jan.


正解はあり"$@"ません、すべての引用された、"$1""$2"、...の位置偶然にも$*
Samveen 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.