
私は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
.bashrc
Bashの起動時にエラーや警告が表示されないため、それ自体に問題はないと確信しています。追加のデバッグを通じて.profile
購入したことがわかりました。.bashrc
# source Bash customizations
[ -n "${BASH_VERSION}" ] && [ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc"
このように~/.bashrc
始めました。
# If not running interactively, don't do anything
[[ "$-" != *i* ]] && return
質問:
- なぜ始める前にリソースを確保する
man
必要がありますか?.profile
- 二重チェックにもかかわらず、上記のコードがBashではなくシェルで解析されるのはなぜですか?
- Bashではない場合、
.profile
ソースコードが得られないことを確認してください。.bashrc
.bashrc
さらに処理を中止するには、非対話式にチェックインしてください。
- Bashではない場合、
@muruのコメントを通して、Bashではなくシェルからインポートする危険があるので、エクスポートされた関数にBashismを含めてはいけないことに気づきました。残りの質問:なぜman
電話するのですsh
か?。
答え1
man
あなたのものを読みませんが、いくつかのコマンドラインを解釈するために~/.profile
実行されます(または少なくとも私のシステムではスクリプトラッパーを解釈します)。そしてあなたのシステムでは:sh
nroff
sh
groff
sh
bash
輸入bash
export -f
(shellshockの後に名前付き変数から)BASH_FUNC_funcname%%
によってエクスポートされた関数、sh
。
extglob
ここでは、このオプションによって構文が異なる関数をエクスポートしています。したがって、実行sh
(モードbash
で)してエクスポートされたすべての機能をインポートすると、デフォルトで有効なオプション(モードであるかどうか)ではないsh
ため、問題を解決できません。extglob
sh
IOW、関数のエクスポートは、その関数がすべての呼び出しで使用されることを意味しますbash
。sh
したがって、sh
これらの関数の構文が-as-in-default設定と互換性があることにbash
注意する必要があります。それ以外の場合は、関数のエクスポートをすべて避ける必要があります。これらの関数が呼び出されなくても、これらの関数のコードも解析されます。bash
sh
bash
望むより:
$ 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
またはオプション(最近のバージョンで設定されたオプションを除く)とは逆に)、関数が呼び出されるまで遅延解析を使用し、オプションが設定されますされました。ksh
set
eval
extglob
ここでも次のことができます。
f() (
shopt -s extglob
pattern='*.?(ba)sh'
case ... in
($pattern)...
esac
)
ただし、次のようにすることもできます。
f() {
case ... in
(*.sh | *.bash) ...
esac
}
これはsh
必要ありませんextglob
。
答え2
関数、特に基本以外の bash 構成を必要とする関数をエクスポートしないでください。
エクスポートされた関数はbash機能なので、他のシェルには影響しません。しかし、これはbashへのすべての呼び出しに影響します。関数でextglob
このオプションを有効にする必要があります。それ以外の場合、関数の実行が失敗するだけでなく、分析する関数の定義に失敗しました。関数をエクスポートすると、bashは操作を開始する前に関数定義を解析します。
シェルはsh
Unixシステムのグルーコードです。インタラクティブに使用するだけでなく、後ろでも広く使用されています。プロシージャ呼び出しはsh
さまざまな目的で使用されます。man
複数のコンパニオンプログラムを呼び出します。そのうちの1つはシェルを呼び出すことができます。たとえば、Linuxでのnroff
一般的な実装(マンページのソースコードを端末のリッチテキストに変換する基本的なコマンド)はgroff
伝統的です。 、ディストリビューションによっては、dash、bash(またはLinuxではまれですが、他の実装)かもしれません。nroff
nroff
sh
インタラクティブな使用の場合、bashはロードするので、.bashrc
環境に関数を置くことは意味がありません。その定義を.bashrc
、またはfromに入れます.bashrc
。独自のスクリプトの場合は、関数定義を目的のファイルに入れます(.profile
または.bashrc
それ自体が含まれているため)。すべてのスクリプトに対して実行してはいけません)、スクリプトにまたはコマンドを入れてくださいsource
。.
関数定義をエクスポートする利点はほとんどありません。これを使用するスクリプトを制御するので、定義された場所を取得することができます。 Bashがデフォルト設定で関数を解析できない場合、関数が機能する方法はありません。