
他のPOSIX互換シェルは、bashの合理的な代替としてどの程度まで使用できますか?彼らは真の「直接」代替物である必要はありませんが、協力するのに十分近いはずです。最大スクリプトを作成し、いくつかの修正で残りをサポートします。
最小限の修正で機能するために、明示的なbashスクリプト(initscripts、DHCPクライアントスクリプトなど)が必要です。
私自身のより専門的なシェルスクリプトコレクションが多くの修正を必要としないことを願っています。
文字列の操作や組み込みの正規表現パターンマッチングなどの機能が欲しいです。
私が知る限り、唯一の深刻な競争相手はzshとmkshです。したがって、どちらか一方または両方に上手な方のために:
zshとmkshにはありませんが、bashにはどのような機能がありますか?
シェルはbashとどのような機能を共有しますが、互換性のない構文を使用しますか?
答え1
スクリプト機能を引き続き使用します。豊富なインタラクティブ機能(コマンドライン編集、完成、プロンプトなど)は非常に多様で、完全に互換性のない方法で同様の効果を得る傾向があります。bashにはないzshには何の機能もなく、その逆の場合もありますか?一部のポインタは対話型の使用のために提供されます。
bashに一番近いのはATT ksh93またはムケシ(Kornシェルとクローン)。 Zshにもいくつかの機能がありますが、zshデフォルトモードではなくkshエミュレーションモードで実行する必要があります。
私はそれらをリストしません。POSIX関数(すべての最新のシェルで利用可能sh
)または対話式の使用のために上記の比較的曖昧な関数ではありません。観察は、Debian wheezyで見つかったbash 4.2、ksh 93u、およびmksh 40.9.20120630から有効です。
シェル構文
引用する
$'…'
(バックスラッシュ補間を含むリテラル文字列)ksh93とmkshで使用できます。 `$"..." (翻訳された文字列) は bash に固有のものです。
条件付き構成
mkshとksh93は;&
ステートメントで失敗する必要がありますcase
が、;;&
後続のケースはテストできません。 Mkshはすでに;|
これを行っており、最近のmkshでは;;&
互換性があります。
((…))
算術式と[[ … ]]
テストはksh関数です。一部の条件演算子は異なります。下記の「条件式」をご覧ください。
共同プロセス
Kshとbashの両方が共同プロセスを持っていますが、異なる動作をします。
機能
Mkshとksh93はfunction name {…}
標準に加えて関数定義の構文をサポートしていますname () {…}
が、function
kshで使用するとスコープルールが変更されるため、name () …
互換性を維持する必要があります。関数名に許可される文字規則は英数字と_
。
サポート拡張
Ksh93とmkshは中括弧拡張をサポートしています{foo,bar}
。 Ksh93は数値範囲をサポートしています{1..42}
が、mkshはサポートしていません。
パラメータ拡張
${VAR:offset}
Ksh93とmkshは、部分文字列の抽出をサポートしていますが、大文字と小文字の${VAR:offset:length}
区別はサポートしていません${VAR^}
。大文字と小文字を変換するために${VAR,}
bashとkshでandを使用できますtypeset -l
。typeset -u
${VAR/PATTERN/STRING}
の使用または交換をサポートします${VAR/PATTERN//STRING}
。 STRINGの引用規則は多少異なるため、STRINGにバックスラッシュ(および他の文字も使用可能)を使用しないでください。変数を作成し、${VAR/PATTERN/$REPLACEMENT}
代替項目に引用符が含まれている場合は代わりに使用してください。
配列拡張(${ARRAY[KEY]}
、、、、、)は"${ARRAY[@]}"
、kshと同様にbashでも同じように動作します。${#ARRAY[@]}
${!ARRAY[@]}
${!VAR}
拡張される値(間接変数を参照)${OTHERVAR}
はbashによって異なります(kshは他の操作を実行します)。 kshでこれらの二重拡張を取得するには、名前参照()を使用する必要があります。動作原理は同じです。VAR
OTHERVAR
${!VAR}
typeset -n VAR=OTHERVAR; echo "$VAR"
${!PREFIX*}
プロセスの置き換え
ksh93はプロセスの交換をサポートしています<(…)
が、>(…)
mkshはサポートしていません。
ワイルドカードパターン
shopt -s extglob
bash でアクティベーションが必要な ksh 拡張 glob モードは、ksh93 および mksh で常に使用できます。
Mkshは次のことをサポートしていません[[:alpha:]]
。
IOリダイレクト
Bashとksh93は擬似ファイルとmkshを定義しますが、mkshはそうではありません。/dev/tcp/HOST/PORT
/dev/udp/HOST/PORT
スクリプトのリダイレクトでは、ワイルドカード拡張(ファイル名がパターンと一意に一致するかどうかを作成するなどvar="*.txt"; echo hello >$a
)はbash専用の機能です(他のシェルはスクリプトではこれを行いません)。a.txt
<<<
ここの文字列はbashと同様にkshでも動作します。
>&
mkshは構文エラーのあるショートカットリダイレクトもサポートしていますが、ksh93はサポートしていません。
条件式
[[ … ]]
二重括弧構文
ATT ksh93 と mksh はどちらも bash と同様に ksh で二重角かっこ構文をサポートします。
ファイル演算子
Ksh93、mksh、およびbashは、(sticky)、(egid所有)、(euid所有)、(同じファイル)、(最新)、(より)など、廃止された同義語を含む同じPOSIX拡張をサポートします-a
。-e
-k
-G
-O
-ef
-nt
-ot
-N FILE
(最後の読み取り以降に修正されました)mkshではサポートされていません。
Mkshには正規表現一致演算子はありません=~
。 Ksh93はbashと同じ一致を実行しますが、一致するグループを検索するのと同じ演算子はありませんBASH_REMATCH
。
文字列演算子
Ksh93とmkshはbashと同じ文字列比較演算子をサポートしています<
。 Mkshは、アルファベット順を決定するためにロケールを使用せずに、文字列をバイト文字列として比較します。>
==
=
その他のオペレータ
-v VAR
変数がbash固有のものとして定義されているかどうかをテストします。すべてのPOSIXシェルから[ -z "${VAR+1}" ]
。
組み込み機能
alias
エイリアスに許可される文字セットは、すべてのシェルで同じではありません。私はこれが関数と同じだと思います(上記を参照)。
builtin
Ksh93には組み込みコマンドがありますが、builtin
その名前を組み込みコマンドとして実行するわけではありません。エイリアスと関数をバイパスするために使用されます。組み込みコマンドがある場合は呼び出し、それ以外の場合は外部コマンドを呼び出します(command
これを使用すると回避できます)。PATH= command error_out_if_this_is_not_a_builtin
caller
これはbash専用です。 ksh93では、を使用して同様の効果を得ること.sh.fun
ができます.sh.file
。.sh.lineno
mkshがついにそれを持つようになりましたLINENO
。
declare
、local
、typeset
declare
kshのbash固有の名前typeset
。使用法typeset
:bashでも動作します。
local
Mkshはのエイリアスとして定義されますtypeset
。 ksh93では、typeset
エイリアスを使用(または定義)する必要があります。
Mkshには連想配列はありません(未リリースのバージョンでは予想されます)。
typeset -t
kshにはbash(追跡機能)とまったく同じ機能があるとは思いません。
cd
Ksh93-e
番号。
echo
Ksh93とmkshはbashと同様に-e
オプションを処理します。-n
mkshは-E
ksh93がそれをオプションとして扱わないことも理解しています。バックスラッシュ拡張はksh93ではデフォルトでオフになっており、mkshではデフォルトでオンになっています。
enable
Kshは組み込みコマンドを無効にする方法を提供しません。組み込みコマンドを使用しない場合は、外部コマンドへのパスを見つけて明示的に呼び出します。
exec
Ksh93はい、-a
しかしいいえ-l
。 Mkshには両方ありません。
export
ksh93またはmkshにはこの機能はありませんexport -n
。typeset +x foo
代わりにこれを使用すると、bashとkshで動作します。
Kshは環境を介して機能をエクスポートしません。
let
let
bashとkshでも同様です。
mapfile
、readarray
これはbash固有の機能です。while read
ループまたはコマンド置換を使用してファイルを読み取り、行配列に分割することができます。管理IFS
とワイルドカード。これは次のとおりですmapfile -t lines </path/to/file
。
IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f
printf
printf
とても似ています。 ksh93はbashのすべてのフォーマットガイドラインをサポートすると思います。 mkshは%q
またはをサポートしません%(DATE_FORMAT)T
。一部のインストールでは、printf
mksh 組み込みコマンドの代わりに外部コマンドが呼び出されます。
printf -v VAR
bash 固有の ksh は常に標準出力として出力します。
read
readlineに関連するすべてのオプションを含むいくつかのオプションはbashにのみ適用されます。オプション-r
、、、、はbash、ksh93、およびmkshで-d
同じです。-n
-N
-t
-u
readonly
同じ構文を使用して、Ksh93とmkshで変数を読み取り専用として宣言できます。変数が配列の場合は、まず割り当ててからそれを使用して読み取り専用にする必要がありますreadonly VAR
。 kshの機能は読み取り専用にすることはできません。
set
、shopt
set
とのすべてのオプションはset -o
POSIXまたはksh機能です。
shopt
bash専用です。それにもかかわらず、多くのオプションには対話型の使用が含まれます。ワイルドカードやその他の機能に対するいくつかのオプションの効果については、以下のオプションセクションを参照してください。
source
.
この亜種はkshにも存在します。 bashとmkshでは。source
次に現在のディレクトリを検索するがPATH
、ksh93では.
。
trap
DEBUG
偽の信号は mksh では実装されません。 ksh93は情報を異なって報告します。詳しくはマニュアルをご覧ください。
type
kshtype
ではwhence -v
。 mkshでは、type -p
実行可能ファイルのパスを印刷するのではなく、人間が読めるメッセージが印刷されますwhence -p COMMAND
。
オプション
shopt -s dotglob
- ワイルドカードのドットファイルを無視しないでください。
dotglob
ksh93のオプションをエミュレートするには、を設定できますFIGNORE='@(.|..)'
。 mkshにはそんなことがないようです。
shopt -s extglob
— ksh 拡張グローバルモード
このextglob
オプションはkshでは常に有効です。
shopt -s failglob
- globパターンが何も一致しない場合、エラーが発生します。
私はこれがmkshまたはksh93には存在しないと思います。 zshで実行されます(null_glob
設定されていない場合はデフォルトの動作)。csh_null_glob
shopt -s globstar
- 再帰 **/
的なワイルドカード
Ksh93には、**/
を通じてアクティブにできる再帰的なワイルドカードがありますset -G
。 Mkshには再帰的なワイルドカードはありません。
shopt -s lastpipe
- 親シェルでパイプラインの最後のコマンドを実行します。
Ksh93は常に親シェルでパイプラインの最後のコマンドを実行するため、lastpipe
bashでこのオプションを設定する必要があります。 Mkshは常にサブシェルでパイプラインの最後のコマンドを実行します。
shopt -s nocaseglob
, shopt -s nocasematch
— 大文字と小文字を区別しないモード
Mkshには大文字と小文字を区別しないパターンマッチング機能はありません。 Ksh93はパターンごとにこれをサポートしています。パターンの前に~(i)
。
shopt -s nullglob
- 一致するファイルのないパターンを空のリストに展開します。
Mkshにはこれはありません。 Ksh93はパターンごとにこれをサポートしています。パターンの前に~(N)
。
変わりやすい
明らかに、ほとんどのBASH_xxx
変数はkshには存在しません。$BASHPID
高価ですが、ポータブルでエミュレートすることができ、sh -c 'echo $PPID'
最近はmkshに追加されました。 ksh93とmkshにBASH_LINE
あります。 ksh93に位置 。.sh.lineno
LINENO
BASH_SUBSHELL
.sh.subshell
ENV
Mkshとksh93はどちらも起動時に提供されたファイルを取得します。
EUID
UID
ksh93には存在しません。 MkshUSER_ID
はそれらを呼びませKSH_UID
んGROUPS
。
FUNCNAME
FUNCNEST
kshには存在しません。 Ksh93.sh.fun
と.sh.level
。 (括弧なしで!)とfunction foo { …; }
宣言された関数はにあります$0
。
GLOBIGNORE
ksh93には存在しますが、名前と構文が異なります。と呼ばれ、FIGNORE
コロンで区切られたリストではなく単一パターンです。使用@(…|…)
モード。 KshにはFIGNORE
bashが含まれていますが、構文はまったく異なります。
Ksh93やmkshのようなものはありませんHOSTTYPE
。または。MACHTYPE
OSTYPE
SHELLOPTS
TIMEFORMAT
Mkshにはありますが、PIPESTATUS
ksh93にはありません。
Mkshおよびksh93にRANDOM
。
答え2
この質問は広すぎます。
両方ムケシそして扱いにくい多くのシェルをサポートしています。GNU バッシュ- 特定の拡張があるが常に理解されていない部分があります。
zshははるかに多くをサポートしていますが、GNU bashなどのPOSIXシェルと互換性のあるデフォルトのzshモードでのみサポートされています。AT&T ksh93、mksh)。さらに、mkshはより薄く、より速く、移植性に優れています。
一般的に、この場合あなたの私たちはスクリプトについて話しています。引き続きテストしてみてください。 (mkshはまだbash4スタイルの連想配列をサポートしていません。 "declare"コマンドはbashに固有のもので、 "typeset"は同じです。私はzshについて直接話すのに慣れていません。 「typeset」も使用します。)しかし、これがbashのないDebianシステムを実行することであるならば、忘れてください。
免責事項:私はmksh開発者です。
答え3
しかし、最近ではある程度拡張が交差している。 Zsh (3.1.6 ベース) には、bash の
${var/old/new}' feature for replacing the text old with the text new in the parameter $var. Note one difference here: while both shells implement the syntax
${var/#old/new}' と${var/%old/new}' for anchoring the match of old to the start or end of the parameter text, respectively, in zsh you can't put the
#' または {var/$old/new}' があります。ここで、oldは文字列の先頭に一致するように(#s) '%' inside a parameter: in other words
で始まります。#' treats that as an ordinary character in zsh, unlike bash. To do this sort of thing in zsh you can use (from 3.1.7) the new syntax for anchors in any pattern,
, そして "(#e)" は終了と一致します。これを行うには、EXTENDED_GLOBオプションを設定する必要があります。
私はmkshについてよく知らないので、どこで答えを見つけるべきかわかりません。
シェルの安全な選択肢を探しているならば、これは議論された固有の欠陥の点でBashと大きく変わりません。
Perlのような言語は入力をより安全に扱います。しかし、ここでもメンテナンス性が重要です。 Perlシェルの代替はうまく採用されていません。入力を安全に処理することはシェル管理者の責任です。だからスクリプトを書くとき、すべてを確認し、確認して確認してください!コード契約を使用して毎回正しい結果を得る!
答え4
機能いいえデフォルトで有効mksh
シェルの歴史です。
設定した内容は次のとおりです
.mkshrc
。export HISTFILE=~/.mksh-history