シェル変数の設定後に子プロセス呼び出しが失敗する

シェル変数の設定後に子プロセス呼び出しが失敗する

OPTERR私は動作に影響を与えるシェル変数を持つgetoptsを使用しています。OPTERRgetoptsの動作に影響を与えるために、getoptsの値を変更して同じ行からgetoptsを呼び出したいのですが、デフォルト値にOPTERR戻したいと思います。したがって、変数変更コマンドの呼び出しを混在させるプロセスについて少し曖昧であることを考慮して、簡単なことを試してみましょうecho。これは一連のシェルコマンドとその出力で、そのうちのいくつかは私には理解されていません。

$ echo OPTERR
1
$ OPTERR=0 echo $OPTERR
1

今はここで止まります。 2番目のコマンドの出力は「0」でなければなりませんか?それで、この質問をする前に、私は頭をつかみ、次のコマンドがサブシェルにある必要があるので、それがあると思いました。だから試してみました...

$ OPTERR=0 (echo $OPTERR)
-bash: syntax error near unexpected token `('

これはもっと驚くべきことです。上記の構成に構文エラーがある場合は、サブシェルを実行するためにシェル変数の値をどのように変更できますか? (また、echoコマンドの後に端末「;」を入れようとしましたが、同じ結果が得られました。)私も試してみました...

$OPTERR=0 bash -c 'echo $OPTERR'
1

したがって、そこにも喜びはありません。別の方法を選んだが..

$function sf() { echo $OPTERR }
$sf
1
$OPTERR=0 sf
0
$sf
1

成功! !しかし、なぜ?この機能は特にサブシェルではなく(そうではありません)、これは実際に私が望むものではありません(私のアプリケーションで動作するようにすることはできますが)。動作する別の式は次のとおりです。

$function sf() { (OPTERR=0; echo $OPTERR;) }
$sf
0
$echo $OPTERR
1

これは私が望むものと非常に似ていますが、もちろん実際のスクリプト(私は些細なことではありません)はこれをecho行うことを意図しており、スクリプトの残りの部分で見ることができる変数を変更する必要があります。そのため、単純なスクリプトを次の単純な変数セットに変更しました。getoptsgetoptsecho

$function sf() { foo='bar'; (foo='check'; echo $foo;); echo $foo; }
$sf
check
bar

ああ! !だからgetopts私が望む環境に呼び出すことはできますが、サブシェルでは何の値も取得できません。私はここにリストするにはあまりにも恥ずかしいfooとすべての種類のアイテムをエクスポートしようとしましたが、ここに私の問題があります。私のすべての実験をまとめると、これらすべてがどのように機能するのかという根本的に間違ったモデルが明らかになります。私の理解には何がありましたか?正しいアプローチは何ですか?

もう一度申し上げますが、私がしたいのは、withを使用してゼロに設定される関数を作成することですgetoptsOPTERR理想的には、関数を呼び出される行に設定せずに、OPTERR関数の外部から復元するように設定することです。ほとんどのOPTERR重要なことは、実際に処理できる方法でgetopts問題が多いように聞こえますが、かなり合理的であり、OPTERRこの変数の存在はそれが可能でなければならないことを示唆しています。

ベストアンサー1

$ echo $VAR

$VARこれは、シェルがコマンドラインから展開した後にのみ変数割り当てを適用するため、以前の値を提供します。

IFS= read -r fooただし、Webサイトでよく見られる構成は、コマンドラインからインポートするのでreadはなく内部で使用するために機能します。IFS同様にOPTERR=0 getopts ...動作する必要があります。

$ cat arg.sh
#!/bin/bash
OPTERR=0 getopts a:b var
echo "var: $var OPTERR: $OPTERR"

$ bash arg.sh -z
var: ? OPTERR: 1

オプションが無効な場合でも、-zエラーメッセージは表示されません。


$ OPTERR=0 bash -c 'echo $OPTERR'

特別なのでちょっと特別ですOPTERR。 Bashのマニュアルページは次のように述べています。

OPTERR値に設定すると、 1Bashは組み込みコマンドによって生成されたエラーメッセージを表示しますgetoptsOPTERRシェルが呼び出されるか、シェルスクリプトが実行されるたびに 1 に初期化されます。

しかし、アイデアは正確であり、通常の変数で動作します。

$ FOO=123 bash -c 'echo $FOO'
123

私がしたいのは、次のような関数を作成することです。getopts

関数の引数を解析し、それをネイティブプログラム(たとえばdothis -a; dothis -b -c)から数回呼び出し、その関数を使用してシェルの引数()を解析しない場合は、変数も変更する必要があることにparse_args "$@"注意してください。また、その機能に合わせてローカライズする必要があります。getoptsOPTIND

たとえば、ここでは、2番目の関数呼び出しにオプションは表示されません。

foo() { while getopts "abcd" opt; do echo "$opt"; done; };
foo -a -a
foo -b -b

以前の機能と組み合わせると、この機能は自動的に機能します。

foo() {
    local OPTIND=1
    while OPTERR=0 getopts "abcd" opt; do
        echo "$opt"
    done
}

おすすめ記事