なぜ人々は.profileで定義されている機能について文句を言うのですか?

なぜ人々は.profileで定義されている機能について文句を言うのですか?

私はBash 5.1.8を使用しています。実行すると、manマニュアルページが表示されますが、次のエラーが発生します。

man ps

sh: bat: line 10: syntax error near unexpected token `('
sh: bat: line 10: ` *.?(ba)sh)'
sh: error importing function definition for `bat'

私の考えでは、いくつかのシェル(sh)はBashismを迷惑にするようです。 Bash-ismsを以下から削除すると~/.bashrc:

    function bat {
        # lines snipped for brevity

        case "$f" in
            *.rs      ) opt_syntax="--syntax=rust";;
            *.?(ba)sh ) opt_syntax="--syntax=shellscript";;
            *.?(m)m   ) opt_syntax="--syntax=objc";;
        esac

        # lines snipped for brevity
    }
    export -f bat

.bashrcBashの起動時にエラーや警告が表示されないため、それ自体に問題はないと確信しています。追加のデバッグを通じて.profile購入したことがわかりました。.bashrc

# source Bash customizations
[ -n "${BASH_VERSION}" ] && [ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"

このように~/.bashrc始めました。

# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return

質問:

  1. なぜ始める前にリソースを確保するman必要がありますか?.profile
  2. 二重チェックにもかかわらず、上記のコードがBashではなくシェルで解析されるのはなぜですか?
    1. Bashではない場合、.profileソースコードが得られないことを確認してください。.bashrc
    2. .bashrcさらに処理を中止するには、非対話式にチェックインしてください。

@muruのコメントを通して、Bashではなくシェルからインポートする危険があるので、エクスポートされた関数にBashismを含めてはいけないことに気づきました。残りの質問:なぜman電話するのですshか?

ベストアンサー1

manあなたのものを読みませんが、いくつかのコマンドラインを解釈するために~/.profile実行されます(または少なくとも私のシステムではスクリプトラッパーを解釈します)。そしてあなたのシステムでは:shnroffshgroffshbash輸入bashexport -f(shellshockの後に名前付き変数から)BASH_FUNC_funcname%%によってエクスポートされた関数、sh

extglobここでは、このオプションによって構文が異なる関数をエクスポートしています。したがって、実行sh(モードbashで)してエクスポートされたすべての機能をインポートすると、デフォルトで有効なオプション(モードであるかどうか)ではないshため、問題を解決できません。extglobsh

IOW、関数のエクスポートは、その関数がすべての呼び出しで使用されることを意味しますbashshしたがって、shこれらの関数の構文が-as-in-default設定と互換性があることにbash注意する必要があります。それ以外の場合は、関数のエクスポートをすべて避ける必要があります。これらの関数が呼び出されなくても、これらの関数のコードも解析されます。bashshbash

望むより:

$ env 'BASH_FUNC_f%%=() { case x in ?(x)) echo x; esac; }' bash -O extglob -c f
x
$ env 'BASH_FUNC_f%%=() { case x in ?(x)) echo x; esac; }' bash -c f
bash: f: line 0: syntax error near unexpected token `('
bash: f: line 0: `f () { case x in ?(x)) echo x; esac; }'
bash: error importing function definition for `f'
bash: line 1: f: command not found

関数にこのような解析に影響を与えるデフォルト以外のオプションが必要な場合は、extglob次のように定義できます。

f() (
  shopt -s extglob
  eval '
    function body here
  '
)
export -f f

これは、オプションが関数の実行中にのみ設定されるようにサブシェルでコードを実行し(ローカル範囲を持たないbashオプションzshまたはオプション(最近のバージョンで設定されたオプションを除く)とは逆に)、関数が呼び出されるまで遅延解析を使用し、オプションが設定されますされました。kshsetevalextglob

ここでも次のことができます。

f() (
  shopt -s extglob
  pattern='*.?(ba)sh'
  case ... in
    ($pattern)...
  esac
)

ただし、次のようにすることもできます。

f() {
  case ... in
    (*.sh | *.bash) ...
  esac
}

これはsh必要ありませんextglob

おすすめ記事