zshとmkshはbashと互換性がないのですか?


11

他のPOSIX互換シェルは、bashの合理的な代替としてどの程度機能しますか?それらは真の「ドロップイン」置換である必要はありませんが、ほとんどのスクリプトで動作し、いくつかの変更を加えて残りをサポートするのに十分近いです。

  1. 明示的なbashスクリプト-initscripts、DHCPクライアントスクリプトなど-を最小限の変更で機能させたい

  2. より多くの変更を必要としない、より専門的なシェルスクリプトの独自のコレクションが欲しい

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

私が知っている深刻な候補はzshとmkshだけです。ですから、ここのどちらかまたは両方に長けているあなたのために:

  1. bashには、zshとmkshにそれぞれない機能がありますか?

  2. シェルはbashとどの機能を共有しますが、互換性のない構文を使用しますか?


3
コマンドシェルの比較:(en.wikipedia.org/wiki/Comparison_of_command_shells)Bashスクリプトの詳細ガイド:(tldp.org/LDP/abs/html)ZSHマニュアル:(zsh.sourceforge.net/Guide/zshguide.html)MirBSDシェルマニュアル:(mirbsd.org/htman/i386/man1/mksh.htm)。申し訳ありませんが、この質問は複雑すぎます。おそらく、特定のLinuxディストリビューションの脆弱性を修正するためにbashにパッチを当てる方法を尋ねるべきでしょうか?
タイラーマギニス2014年

3
の代わりにドロップとして機能できるシェルはありませんbash。mkshとzshは/bin/sh、さまざまなレベルの正確性と同様に機能できますが、は機能しませんbash
llua 14年

1
シェルショックの全体は核心的な質問とは何の関係もないようで、人々の注意をそらすだけなので、削除しました
Michael Mrozek

3
質問全体が広すぎます。おそらくそれを削除する必要があります。
タイラーマギニス2014年

1
私が本当に懸念している唯一の懸念は、BASHがFree Software Foundation(FSF)によって適切に管理されていることです。私の連絡先は、BASH内の「基本的な欠陥」の暴露は、より強力でより安全な実装につながるだけだと教えてくれました。非常に多くの代替シェルがあり、要件に合わせてシェルを推奨し始めたとしても、私はあなたのユースケースをしっかりと理解する必要があります。次に、O / S側で... Bashには多くのものが関連付けられているため、O / S呼び出し全体をBASHに書き換える可能性があります。私が見ることができる最良の解決策は、alt-shellが維持されているディストリビューションを選択することです。
タイラーマギニス2014年

回答:


19

私はスクリプト機能に固執します。豊富なインタラクティブ機能(コマンドライン版、補完、プロンプトなど)は非常に異なる傾向があり、まったく互換性のない方法で同様の効果を実現します。zshにはどの機能があり、bashにはありませんか、またはその逆ですか?インタラクティブな使用に関するいくつかの指針を示します。

bashに最も近いものは、ATT ksh93またはmksh(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はサポートしていません。

パラメータ拡張

ksh93とmkshサポート部分文字列での抽出${VAR:offset}${VAR:offset:length}ではなく、ケースのような折りたたみは${VAR^}${VAR,}などあなたはと小文字の変換を行うことができますtypeset -lし、typeset -ubashのとkshの両方に。

彼らはとの交換をサポートします${VAR/PATTERN/STRING}${VAR/PATTERN//STRING}。STRINGの引用規則は少し異なるため、STRINGでバックスラッシュ(および他の文字)を避けます(変数を作成し${VAR/PATTERN/$REPLACEMENT}、置換に引用文字が含まれている場合は代わりに使用します)。

アレイの拡張(${ARRAY[KEY]}"${ARRAY[@]}"${#ARRAY[@]}${!ARRAY[@]}kshの中のようなbashで)仕事。

${!VAR}is ${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は定義しません。/dev/tcp/HOST/PORT/dev/udp/HOST/PORT

スクリプト内のリダイレクトでワイルドカードを展開すること(そのファイル名がパターンに唯一一致var="*.txt"; echo hello >$aするa.txt場合の書き込みの場合など)は、bash固有の機能です(他のシェルはスクリプトでそれを行いません)。

<<< here-stringsは、bashのようにkshで機能します。

>&構文エラーをリダイレクトするショートカットもmkshではサポートされていますが、ksh93ではサポートされていません。

条件式

[[ … ]] 二重括弧構文

kshからの二重ブラケット構文は、bashと同様に、ATT ksh93とmkshの両方でサポートされています。

ファイル演算子

ksh93、mkshとbashのサポートなど、POSIXに同じ拡張子、-a旧式の同義語として-e-k(粘着性)、-G(EGIDが所有している)、-O(EUIDによって所有者)、 -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固有です。.sh.fun.sh.fileおよび.sh.linenoksh93 でも同様の効果を得ることができます。mkshにはついにありLINENOます。

declarelocaltypeset

declarekshのbash固有の名前ですtypeset。使用typeset:bashでも機能します。

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

Mkshには連想配列がありません(まだリリースされていないバージョンが予定されています)。

typeset -tkshには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 -ntypeset +x foo代わりに使用してください。bashとkshで動作します。

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

let

let bashと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。一部のインストールでprintfは、mksh組み込みではなく、代わりに外部コマンドを呼び出します。

printf -v VAR bash固有であり、kshは常に標準出力に出力します。

read

readlineに関するすべてのオプションを含む、いくつかのオプションはbash固有です。オプションには-r-d-n-N-t-ubashの、は、ksh93とmkshで同一です。

readonly

同じ構文で、Ksh93とmkshで変数を読み取り専用として宣言できます。変数が配列の場合は、最初に割り当てる必要があり、次にで読み取り専用にしreadonly VARます。kshでは関数を読み取り専用にすることはできません。

setshopt

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

shoptbash固有です。とにかく多くのオプションはインタラクティブな使用に関するものです。一部のオプションによって有効になるグロビングおよびその他の機能への影響については、以下の「オプション」のセクションを参照してください。

source

こののバリアントは.kshにも存在します。bashとmkshでは、のsourcePATHに現在のディレクトリを検索しますが、ksh93では、とまったく同じです.

trap

DEBUG擬似信号はmkshに実装されていません。ksh93では、情報を報告する別の方法で存在します。詳細については、マニュアルを参照してください。

type

kshでは、はのtypeエイリアスですwhence -v。mkshではtype -p、実行可能ファイルへのパスではなく、人間が読めるメッセージを出力します。whence -p COMMAND代わりに使用する必要があります。

オプション

shopt -s dotglob —グロビングでドットファイルを無視しない

dotglobksh93 のオプションをエミュレートするには、を設定できますFIGNORE='@(.|..)'。mkshにはこのようなものはないと思います。

shopt -s extglob — ksh拡張globパターン

この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は常に親シェルでパイプラインの最後のコマンドを実行します。これはbashではlastpipeオプションを設定する必要があります。Mkshは常にパイプラインの最後のコマンドをサブシェルで実行します。

shopt -s nocaseglobshopt -s nocasematch—大文字と小文字を区別しないパターン

Mkshには、大文字と小文字を区別しないパターンマッチングはありません。Ksh93はパターンごとにこれをサポートし~(i)ます。パターンの前にを付けます。

shopt -s nullglob —ファイルに一致しないパターンを空のリストに展開する

Mkshにはこれがありません。Ksh93はパターンごとにこれをサポートし~(N)ます。パターンの前にを付けます。

変数

明らかに、ほとんどのBASH_xxx変数はkshに存在しません。$BASHPID高価ですがポータブルsh -c 'echo $PPID'でエミュレートでき、最近mkshに追加されました。ksh93にしてmkshに。ksh93に。BASH_LINE.sh.linenoLINENOBASH_SUBSHELL.sh.subshell

Mkshとksh93はどちらもENV、起動時に指定されたファイルを提供します。

EUIDそしてUIDksh93には存在しません。MkshはそれらUSER_IDを呼び出しますKSH_UID。ありませんGROUPS

FUNCNAMEそしてFUNCNESTkshには存在しません。Ksh93にはとが.sh.funあり.sh.levelます。function foo { …; }(括弧なし!)で宣言された関数は、で独自の名前を持ってい$0ます。

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

Ksh93とmkshにはHOSTTYPEMACHTYPEやのようなものはありませんOSTYPE。またSHELLOPTSTIMEFORMAT

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

Mkshとksh93にはがありRANDOMます。


(登録されていない)商標「mksh」を文の先頭で正しく再現したくない場合(ここで「 "dd。"」と「 "dd"。」も参照)、「MirBSD代わりに「Korn Shell」。「mksh」の文字を大文字にすることは常に間違っています。ありがとう。
mirabilos 2014年

どの$BASHPIDようにしてエミュレートできますsh -c 'echo $PPID'か?(sh -c 'echo $PPID')Bashで試しましたが、と同じPIDが得られ$$ます。
フランクリンユー

質問の方がこちらに適していると思います。そこで質問をコピーしました。
フランクリンYu

4

この質問は広すぎます。

mkshzshはどちらも多くのGNU bash固有の拡張機能をサポートするシェルですが、理解されていないものも常に存在します。

zshはより多くのものをサポートしますが、POSIXシェル(GNU bash、AT&T ksh93、mkshなど)と互換性がないネイティブzshモードでのみサポートされます。また、mkshはよりスリムで高速で移植性に優れています。

一般に、これが私たちが話しているスクリプトである場合は先に進んで、それらをテストしてください。(mkshはまだbash4スタイルの連想配列をサポートしていません。「declare」コマンドはbash固有であり、「typeset」は同等です。私はzshについてよく知らないので、あからさまなことについて何も述べていません。ksh93には「ローカル」がありませんただし、「タイプセット」も使用します。)しかし、これが、たとえばbashを使用しないDebianシステムの実行に関するものである場合は、忘れてください。bashの存在は「約束」(システムのAPI / ABI)の一部であり、それに大きく依存しています。

免責事項:私はmksh開発者です。


1

シェルの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#'または%' inside a parameter: in other words{var / $ old / new} 'があり、ここでoldは#' 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,(#s)'で始まり、文字列の先頭に一致します。 、および末尾を一致させるための `(#e) '。これらには、オプションEXTENDED_GLOBを設定する必要があります。

私はmkshに慣れていないので、その答えをどこで探すべきかわかりません。

あなたがシェルの安全な代替品を探しているなら、あなたが議論している固有の欠陥に関する限り、これらのシェルはどれもBashとそれほど違いません。

Perlのような言語は、入力をより安全に処理します。ただし、ここでは保守性も重要です。Perlシェルの置き換えはあまり採用されていません。入力を安全に処理するのは、シェルのメンテナの責任です。したがって、スクリプトを作成するときは、すべてを検証、検証、検証してください!コードコントラクトを使用して、毎回正しい結果を保証してください!

Perlシェル

シェルショックに関するFSF声明


他のシェルにも同じ欠陥がある場合(私が見た議論に基づいて、これはやや疑わしいものです)、それは大きな問題です。検証または何かの。その場合は、POSIXを完全に破棄することもできます。
DanL4096 2014年

1
Bashプロジェクトでは、10年間で1日0回の悪用がありました。Microsoft Windowsには、週にすべてゼロ日で10以上のエクスプロイトがあります。これについてBash開発チームに迷惑をかけた人が何人か知っていますか?更新して次に進んでください!それは大したことありません。
タイラーマギニス2014年

1
@ DanL4096。変数をシェルスクリプトに渡してから、その変数に対して十分な健全性チェックを行わなくても、POSIXが無効になるわけではありません。問題は、そもそもシェルスクリプトを書いた人にあります。
fpmurphy 2014年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.