web-dev-qa-db-ja.com

"#!/ bin / sh -a"の-aがsedに影響し、 "set -a"が影響しないのはなぜですか?

次の.shファイルを実行すると、

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

結果はエラーです:

sed:-e expression#1、char 18:無効な範囲の終わり

しかし、次の.shファイルを実行すると、

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

エラーなしで実行されます。 2番目のコードは最初のコードと同等ではないのですか?なぜ最初のエラーですか?

20
Rodrigo

shという名前でbashが呼び出されると、 はこれを実行します

if (Shell_name[0] == 's' && Shell_name[1] == 'h' && Shell_name[2] == '\0')
    act_like_sh++;

その後 POSIXLY_CORRECTシェル変数をy に設定します:

if (act_like_sh)
  {
    bind_variable ("POSIXLY_CORRECT", "y", 0);
    sv_strict_posix ("POSIXLY_CORRECT");
  }

bind_variableは、bind_variable_internalを呼び出します。これは、シェル属性aがオンの場合(-aでシェルを呼び出した場合)、 シェル変数をエクスポート済みとしてマークします。

したがって、最初のスクリプトでは:

#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'

sedは、その環境でPOSIXLY_CORRECT=yを使用して呼び出されます。これにより、[\d001-\d008]について不満が出ます。 (sedに--posixオプションが指定されている場合も同じことが起こります。)

GNU sedでは、\dNNNは、base-10の数値が NNN、ただしPOSIXモードでは、これは角括弧式内では無効になっているため、[\d001-\d008]は文字通り\dなどの文字を意味し、範囲は1から\です。文字コードの順序では、1\の前にあります(範囲には、ゼロを除くすべての数字、すべての大文字、およびいくつかの特殊文字が含まれます)。ただし、使用していたen_US.UTF-8ロケールでは、\1の前にソートされるため、範囲は無効です。

2番目のスクリプトでは:

#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'

シェルでPOSIXLY_CORRECTが設定されている場合でも、エクスポートされないため、環境でPOSIXLY_CORRECTなしでsedが呼び出され、sedはGNU拡張機能で実行されます。

2番目のスクリプトの上部近くにexport POSIXLY_CORRECTを追加すると、sedのクレームも表示されます。

31
Mark Plotnick