関数内の呼び出し元のコマンドライン引数にアクセスする方法は?


95

スクリプトのコマンドライン引数にアクセスする関数をbashで記述しようとしていますが、関数の位置引数に置き換えられています。それらが明示的に渡されない場合、関数がコマンドライン引数にアクセスする方法はありますか?

# Demo function
function stuff {
  echo $0 $*
}

# Echo's the name of the script, but no command line arguments
stuff

# Echo's everything I want, but trying to avoid
stuff $*

3
私はちょっと混乱しています、あなたはそれらを渡さずに引数を求めていますか?
Ravi Vyas

4
はい、重要なのは、関数の引数として渡さずに、関数の内部からコマンドライン引数も取得することです。これは、関数に渡された引数とは無関係にコマンドライン引数に基づいてエラー処理を実行したいというエラー処理状況に関係しています。
DonGar

FYI、$*非常にバギーです-それは変わります./yourScript "first argument" "second argument"./yourscript "first" "argument" "second" "argument"、または変更./yourscript '*.txt'のようなものに./yourscript one.txt two.txt引用符にもかかわらず。
Charles Duffy、

回答:


46

bash refのマニュアルを読んだところ、「スタック」についてよく語られていますが、この項目はBASH_ARGVにキャプチャされているようです。

#!/bin/bash

function argv {
    for a in ${BASH_ARGV[*]} ; do
      echo -n "$a "
    done
    echo
}

function f {
    echo f $1 $2 $3
    echo -n f ; argv
}

function g {
    echo g $1 $2 $3
    echo -n g; argv
    f
}

f boo bar baz
g goo gar gaz

f.shに保存

$ ./f.sh arg0 arg1 arg2
f boo bar baz
farg2 arg1 arg0 
g goo gar gaz
garg2 arg1 arg0 
f
farg2 arg1 arg0 

5
このように配列を分割すると、argsがコマンドラインから逆順になることに注意してください。
Andrew Backer

93

引数をCスタイル(引数の配列+引数の数)にしたい場合は、$@およびを使用できます$#

$#引数の数を示します。
$@すべての引数を提供します。これを配列に変換できますargs=("$@")

だから例えば:

args=("$@")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}

これは${args[0]}実際には1番目の引数であり、スクリプトの名前ではないことに注意してください。


5
これは問題に対処していません-コマンドライン引数をシェル関数に渡すことについて尋ねています。
Cascabel

6
@Jefromi、実際には、質問に完全に答えます。args説明したように事前に初期化しておけば、関数内から配列を使用できます。
vadipp 2013

1
これは、引数を反復するよりもはるかにクリーンです。
フェリックス・ガニオン-グルニエ

1
これはシンプルで簡単です。すばらしい答えです。あなたはこれを7年以上前に投稿したので、未来からこんにちは:2017
SDsolar

のようecho "${args[0]} ${args[1]} ${args[2]}"に引用することをお勧めします。そうでない場合、引数はファイル名の拡張の影響を受けます。
ベンジャミンW.

17
#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#

編集:質問に対する私のコメントを参照してください


16

ラビのコメントは本質的に答えです。関数は独自の引数を取ります。それらをコマンドライン引数と同じにしたい場合は、それらを渡す必要があります。それ以外の場合は、引数なしで関数を明確に呼び出しています。

つまり、コマンドライン引数をグローバル配列に格納して、他の関数内で使用したい場合は、

my_function() {
    echo "stored arguments:"
    for arg in "${commandline_args[@]}"; do
        echo "    $arg"
    done
}

commandline_args=("$@")

my_function

コマンドライン引数commandline_argsには$@$1ではなく、変数を介してアクセスする必要があります。$2、など、彼らが利用可能です。引数配列に直接割り当てる方法はわかりませんが、誰かが知っている場合は教えてください!

また、私が使用して引用した方法にも注意してください。$@これは、特殊文字(空白)がつまらないようにする方法です。


6
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*

function stuff {
  # use script args via the variables you saved
  # or the function args via $
  echo $0 $*
} 


# Call the function with arguments
stuff 1 2 3 4

2

これも同じようにできます

#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $@;do
    echo $i
done;
}
argument $@

次のようにスクリプトを呼び出します

./function_test.sh argument1 argument2

function print() {は、2つの異なる関数宣言形式間のアマルガムです- function print {これは、bashがPOSIX以前(つまり、1991年以前)のkshとの下位互換性のためにサポートするレガシーksh構文でありprint() {、POSIX標準化されています。他のシェルとの互換性を高めるために、どちらか一方を使用することを検討してください。wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

それらを反復するために、shiftキーワード(演算子?)を使用できます。例:

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo $1;
        shift 1;
    done
}
print $*;

2
function print() {は、2つの異なる関数宣言形式間のアマルガムです- function print {これは、bashがPOSIX以前(つまり、1991年以前)のkshとの下位互換性のためにサポートするレガシーksh構文でありprint() {、POSIX標準化されています。他のシェルとの互換性を高めるために、どちらか一方を使用することを検討してください。wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

私の解決策:

次のように、引数を渡さずに、他のすべての関数より前に呼び出される関数スクリプトを作成します。

!/ bin / bash

function init(){ORIGOPT = "-$ @-"}

それ以降、必要に応じてinitを呼び出してORIGOPT変数を使用できます。プラスとして、常に新しい変数を割り当て、ORIGOPTの内容を新しい関数にコピーします。これにより、誰もそれに触れたりしないことを保証できます。それを変更。

「sed -E」を使用して解析しやすくするためにスペースとダッシュを追加しました。また、bashは参照として渡さず、関数がより多くの引数で呼び出されるとORIGOPTを拡張します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.