3

これは、私が抱えている問題を単純化する試みです。変数を設定する関数を定義すると、これは次のシナリオで機能します。

$ function myfunc { res="ABC" ; }
$ res="XYZ"
$ myfunc
$ echo $res
    ABC

したがって、res は myfunc の呼び出しによって変更されています。しかし:

$ res="XYZ"
$ myfunc | echo
$ echo $res
    XYZ

したがって、myfunc がパイプの一部である場合、値は変更されません。パイプが関係している場合でも、myfunc を希望どおりに動作させるにはどうすればよいですか?

(実際のスクリプトでは、"myfunc" はもちろんより精巧な処理を行い、パイプの反対側には無意味なエコーではなく、zenity 進行ダイアログが表示されます)

ありがとう

4

2 に答える 2

4

これはUnixでは不可能です。これをよりよく理解するには、変数が何であるかを知る必要があります。Bashは、すべての定義済み変数を含む2つの内部テーブルを保持します。1つは、現在のシェルにローカルな変数用です。set name=valueを使用して、またはを使用して作成できますname=value。これらはプロセスに対してローカルです。新しいプロセスが作成されるときに、それらは継承されません。

変数を新しい子プロセスにエクスポートするには、変数をでエクスポートする必要がありますexport name。これは、bashに「子供にこの変数の値を表示してもらいたい」ことを示しています。これはセキュリティ機能です。

bashで関数を呼び出すと、現在のシェルのコンテキスト内で実行されるため、すべての変数にアクセスして変更できます。

ただし、パイプはI/Oパイプに接続されているプロセスのリストです。つまり、関数はシェルで実行され、このシェルの出力のみがに表示されechoます。

エクスポートは、エクスポートを行ったシェルによって開始され、次と同じシェルによってmyfunc開始されたプロセスに対してのみ機能するため、エクスポートインでも機能しません。echomyfunc

bash
 +-- myfunc
 +-- echo

それはechoの子ではありませんmyfunc

回避策:

  1. 変数をファイルに書き込みます
  2. XMLや数行など、より複雑な出力形式を使用します。この場合、出力の最初の行は常に変数であり、実際の出力は次の行に表示されます。
于 2012-07-10T08:06:08.433 に答える
4

@Aaronが言ったように、問題はサブシェルで実行されている関数によって引き起こされます。しかし、パイプの代わりにプロセス置換を使用して、bash でこれを回避する方法があります。

myfunc > >(echo)

これはパイプとほぼ同じことを行いますが、myfunc はサブプロセスではなくメイン シェルで実行されます。これは bash のみの機能であり、これを機能させるには #!/bin/bash をシバンとして使用する必要があることに注意してください。

于 2012-07-10T16:06:50.607 に答える