zshとmkshとbashの非互換性は何ですか?

zshとmkshとbashの非互換性は何ですか?

他のPOSIX互換シェルは、bashの合理的な代替としてどの程度まで使用できますか?彼らは真の「直接」代替物である必要はありませんが、協力するのに十分近いはずです。最大スクリプトを作成し、いくつかの修正で残りをサポートします。

  1. 最小限の修正で機能するために、明示的なbashスクリプト(initscripts、DHCPクライアントスクリプトなど)が必要です。

  2. 私自身のより専門的なシェルスクリプトコレクションが多くの修正を必要としないことを願っています。

  3. 文字列の操作や組み込みの正規表現パターンマッチングなどの機能が欲しいです。

私が知る限り、唯一の深刻な競争相手はzshとmkshです。したがって、どちらか一方または両方に上手な方のために:

  1. zshとmkshにはありませんが、bashにはどのような機能がありますか?

  2. シェルは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 () {…}が、functionkshで使用するとスコープルールが変更されるため、name () …互換性を維持する必要があります。関数名に許可される文字規則は英数字と_

サポート拡張

Ksh93とmkshは中括弧拡張をサポートしています{foo,bar}。 Ksh93は数値範囲をサポートしています{1..42}が、mkshはサポートしていません。

パラメータ拡張

${VAR:offset}Ksh93とmkshは、部分文字列の抽出をサポートしていますが、大文字と小文字の${VAR:offset:length}区別はサポートしていません${VAR^}。大文字と小文字を変換するために${VAR,}bashとkshでandを使用できますtypeset -ltypeset -u

${VAR/PATTERN/STRING}の使用または交換をサポートします${VAR/PATTERN//STRING}。 STRINGの引用規則は多少異なるため、STRINGにバックスラッシュ(および他の文字も使用可能)を使用しないでください。変数を作成し、${VAR/PATTERN/$REPLACEMENT}代替項目に引用符が含まれている場合は代わりに使用してください。

配列拡張(${ARRAY[KEY]}、、、、、)は"${ARRAY[@]}"、kshと同様にbashでも同じように動作します。${#ARRAY[@]}${!ARRAY[@]}

${!VAR}拡張される値(間接変数を参照)${OTHERVAR}はbashによって異なります(kshは他の操作を実行します)。 kshでこれらの二重拡張を取得するには、名前参照()を使用する必要があります。動作原理は同じです。VAROTHERVAR${!VAR}typeset -n VAR=OTHERVAR; echo "$VAR"${!PREFIX*}

プロセスの置き換え

ksh93はプロセスの交換をサポートしています<(…)が、>(…)mkshはサポートしていません。

ワイルドカードパターン

shopt -s extglobbash でアクティベーションが必要な 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.linenomkshがついにそれを持つようになりましたLINENO

declarelocaltypeset

declarekshのbash固有の名前typeset。使用法typeset:bashでも動作します。

localMkshはのエイリアスとして定義されますtypeset。 ksh93では、typesetエイリアスを使用(または定義)する必要があります。

Mkshには連想配列はありません(未リリースのバージョンでは予想されます)。

typeset -tkshにはbash(追跡機能)とまったく同じ機能があるとは思いません。

cd

Ksh93-e番号。

echo

Ksh93とmkshはbashと同様に-eオプションを処理します。-nmkshは-Eksh93がそれをオプションとして扱わないことも理解しています。バックスラッシュ拡張はksh93ではデフォルトでオフになっており、mkshではデフォルトでオンになっています。

enable

Kshは組み込みコマンドを無効にする方法を提供しません。組み込みコマンドを使用しない場合は、外部コマンドへのパスを見つけて明示的に呼び出します。

exec

Ksh93はい、-aしかしいいえ-l。 Mkshには両方ありません。

export

ksh93またはmkshにはこの機能はありませんexport -ntypeset +x foo代わりにこれを使用すると、bashとkshで動作します。

Kshは環境を介して機能をエクスポートしません。

let

letbashとkshでも同様です。

mapfilereadarray

これは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。一部のインストールでは、printfmksh 組み込みコマンドの代わりに外部コマンドが呼び出されます。

printf -v VARbash 固有の ksh は常に標準出力として出力します。

read

readlineに関連するすべてのオプションを含むいくつかのオプションはbashにのみ適用されます。オプション-r、、、、はbash、ksh93、およびmkshで-d同じです。-n-N-t-u

readonly

同じ構文を使用して、Ksh93とmkshで変数を読み取り専用として宣言できます。変数が配列の場合は、まず割り当ててからそれを使用して読み取り専用にする必要がありますreadonly VAR。 kshの機能は読み取り専用にすることはできません。

setshopt

setとのすべてのオプションはset -oPOSIXまたはksh機能です。

shoptbash専用です。それにもかかわらず、多くのオプションには対話型の使用が含まれます。ワイルドカードやその他の機能に対するいくつかのオプションの効果については、以下のオプションセクションを参照してください。

source

.この亜種はkshにも存在します。 bashとmkshでは。source次に現在のディレクトリを検索するがPATH、ksh93では.

trap

DEBUG偽の信号は mksh では実装されません。 ksh93は情報を異なって報告します。詳しくはマニュアルをご覧ください。

type

kshtypeではwhence -v。 mkshでは、type -p実行可能ファイルのパスを印刷するのではなく、人間が読めるメッセージが印刷されますwhence -p COMMAND

オプション

shopt -s dotglob- ワイルドカードのドットファイルを無視しないでください。

dotglobksh93のオプションをエミュレートするには、を設定できます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は常に親シェルでパイプラインの最後のコマンドを実行するため、lastpipebashでこのオプションを設定する必要があります。 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.linenoLINENOBASH_SUBSHELL.sh.subshell

ENVMkshとksh93はどちらも起動時に提供されたファイルを取得します。

EUIDUIDksh93には存在しません。 MkshUSER_IDはそれらを呼びませKSH_UIDGROUPS

FUNCNAMEFUNCNESTkshには存在しません。 Ksh93.sh.fun.sh.level。 (括弧なしで!)とfunction foo { …; }宣言された関数はにあります$0

GLOBIGNOREksh93には存在しますが、名前と構文が異なります。と呼ばれ、FIGNOREコロンで区切られたリストではなく単一パターンです。使用@(…|…)モード。 KshにはFIGNOREbashが含まれていますが、構文はまったく異なります。

Ksh93やmkshのようなものはありませんHOSTTYPE。または。MACHTYPEOSTYPESHELLOPTSTIMEFORMAT

Mkshにはありますが、PIPESTATUSksh93にはありません。

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シェルの比較

しかし、最近ではある程度拡張が交差している。 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シェルの代替はうまく採用されていません。入力を安全に処理することはシェル管理者の責任です。だからスクリプトを書くとき、すべてを確認し、確認して確認してください!コード契約を使用して毎回正しい結果を得る!

パールシェル

シェルショックのFSF声明

答え4

機能いいえデフォルトで有効mkshシェルの歴史です。

  • 設定した内容は次のとおりです.mkshrc

    export HISTFILE=~/.mksh-history

関連情報