Inwieweit können andere POSIX-kompatible Shells als angemessener Ersatz für Bash fungieren? Sie müssen keine echten "Drop-In" -Ersetzungen sein, sondern nahe genug, um mit den meisten Skripten zu arbeiten und den Rest mit einigen Änderungen zu unterstützen.
Ich möchte, dass explizite Bash-Skripte - Initskripte, DHCP-Client-Skripte usw. - mit minimalen Änderungen funktionieren
Ich möchte, dass meine eigene Sammlung spezialisierterer Shell-Skripte nicht zu stark modifiziert wird
Ich möchte Funktionen wie String-Manipulation und eingebauten Regex-Pattern-Matching haben
Die einzigen ernsthaften Konkurrenten, die ich kenne, sind zsh und mksh. Also, für diejenigen von euch hier, die gut mit einem oder beiden sind:
Welche Funktionen hat bash, die zsh und mksh nicht haben?
Welche Funktionen teilen sich die Shells mit bash, verwenden jedoch eine inkompatible Syntax?
bash
ersetzen kann, mksh und zsh können wie/bin/sh
bei verschiedenen Korrektheitsstufen funktionieren , aber nichtbash
.Antworten:
Ich bleibe bei den Skriptfunktionen. Umfangreiche interaktive Funktionen (Befehlszeilenausgabe, Vervollständigung, Eingabeaufforderungen usw.) sind in der Regel sehr unterschiedlich und erzielen ähnliche Effekte auf völlig inkompatible Weise. Welche Funktionen sind in zsh enthalten und fehlen in bash oder umgekehrt? gibt einige Hinweise zur interaktiven Verwendung.
Am nächsten an Bash wäre ATT ksh93 oder mksh (die Korn-Shell und ein Klon). Zsh hat auch eine Teilmenge von Funktionen, aber Sie müssten es im ksh-Emulationsmodus ausführen, nicht im nativen zsh-Modus.
Ich werde weder POSIX- Funktionen (die in einer modernen
sh
Shell verfügbar sind ) noch relativ undurchsichtige Funktionen oder wie oben erwähnt Funktionen für die interaktive Verwendung auflisten. Die Beobachtungen gelten ab Bash 4.2, ksh 93u und mksh 40.9.20120630, wie sie auf Debian Wheezy zu finden sind.Shell-Syntax
Zitieren
$'…'
(Literalstrings mit Backslash-Interpolation) ist in ksh93 und mksh verfügbar. `$" ... "(übersetzte Zeichenfolgen) ist bash-spezifisch.Bedingte Konstrukte
Mksh und ksh93 müssen
;&
in einercase
Anweisung durchfallen , aber;;&
nachfolgende Fälle nicht testen. Mksh hat;|
dafür und aktuelles Mksh ermöglicht;;&
Kompatibilität.((…))
arithmetische Ausdrücke und[[ … ]]
Tests sind ksh-Merkmale. Einige bedingte Operatoren unterscheiden sich, siehe „Bedingte Ausdrücke“ weiter unten.Coprozesse
Ksh und Bash haben beide Coprozesse, aber sie funktionieren unterschiedlich.
Funktionen
Mksh und ksh93 unterstützen
function name {…}
zusätzlich zum Standard die Syntax für Funktionsdefinitionen. Diename () {…}
Verwendungfunction
in ksh ändert jedoch die Gültigkeitsbereichsregeln.name () …
Halten Sie sich daher an die Kompatibilität. Die Regeln für zulässige Zeichen in Funktionsnamen variieren. halte dich an alphanumerische Zeichen und_
.Klammererweiterung
Ksh93 und mksh unterstützen die Erweiterung der Zahnspange
{foo,bar}
. Ksh93 unterstützt numerische Bereiche{1..42}
, mksh jedoch nicht.Parametererweiterung
Ksh93 und mksh Unterstützung Teilzeichenfolge Extraktion mit
${VAR:offset}
und${VAR:offset:length}
, aber nicht Fall Falten wie${VAR^}
,${VAR,}
usw. Sie können mit Fall Konvertierung zu tuntypeset -l
undtypeset -u
in beiden bash und ksh.Sie unterstützen den Ersatz durch
${VAR/PATTERN/STRING}
oder${VAR/PATTERN//STRING}
. Die Anführungszeichen für STRING unterscheiden sich geringfügig. Vermeiden Sie daher Backslashes (und möglicherweise andere Zeichen) in STRING (erstellen Sie eine Variable und verwenden Sie sie${VAR/PATTERN/$REPLACEMENT}
stattdessen, wenn die Ersetzung Anführungszeichen enthält).Array - Erweiterung (
${ARRAY[KEY]}
,"${ARRAY[@]}"
,${#ARRAY[@]}
,${!ARRAY[@]}
) Arbeit in bash wie in KSH.${!VAR}
Erweitern auf,${OTHERVAR}
wenn der Wert vonVAR
isOTHERVAR
(indirekte Variablenreferenz) bash-spezifisch ist (ksh macht etwas anderes mit${!VAR}
). Um diese doppelte Erweiterung in ksh zu erhalten, müssen Sie stattdessen eine Namensreferenz verwenden (typeset -n VAR=OTHERVAR; echo "$VAR"
).${!PREFIX*}
funktioniert genauso.Prozesssubstitution
Prozessersetzung
<(…)
und>(…)
wird in ksh93, aber nicht in mksh unterstützt.Platzhaltermuster
Die erweiterten ksh-Glob-Muster,
shopt -s extglob
die in bash aktiviert werden müssen , sind immer in ksh93 und mksh verfügbar.Mksh unterstützt keine Charakterklassen wie
[[:alpha:]]
.IO-Umleitung
Bash und ksh93 definieren Pseudodateien und , mksh jedoch nicht.
/dev/tcp/HOST/PORT
/dev/udp/HOST/PORT
Das Erweitern von Platzhaltern in einer Umleitung in Skripten (wie beim
var="*.txt"; echo hello >$a
Schreiben,a.txt
wenn dieser Dateiname die einzige Übereinstimmung mit dem Muster ist) ist eine Bash-spezifische Funktion (andere Shells tun dies niemals in Skripten).<<<
Here-Strings funktionieren in ksh wie in bash.Die Verknüpfung
>&
zum Umleiten von Syntaxfehlern wird auch von mksh unterstützt, nicht jedoch von ksh93.Bedingte Ausdrücke
[[ … ]]
Syntax mit doppelten KlammernDie Double-Bracket-Syntax von ksh wird sowohl von ATT ksh93 als auch von mksh wie in bash unterstützt.
Dateibetreiber
Ksh93, mksh und Bash unterstützt die gleichen Erweiterungen POSIX, darunter
-a
als veraltet Synonym für-e
,-k
(klebrig),-G
(von egid Besitz),-O
(Inhaber von euid),-ef
(gleicher Datei),-nt
(neuer als),-ot
(älter als).-N FILE
(geändert seit dem letzten Lesen) wird von mksh nicht unterstützt.Mksh hat keinen Regexp-Matching-Operator
=~
. Ksh93 hat diesen Operator und führt den gleichen Abgleich wie in bash durch, hat jedoch nicht das ÄquivalentBASH_REMATCH
, um übereinstimmende Gruppen anschließend abzurufen.String-Operatoren
Ksh93 und mksh unterstützen dieselben Zeichenfolgenvergleichsoperatoren
<
und>
als bash sowie das==
Synonym von=
. Mksh verwendet keine Gebietsschemaeinstellungen, um die lexikografische Reihenfolge zu bestimmen, sondern vergleicht Zeichenfolgen als Bytezeichenfolgen.Andere Betreiber
-v VAR
zu testen, ob eine Variable definiert ist, ist bash-spezifisch. In jeder POSIX-Shell können Sie verwenden[ -z "${VAR+1}" ]
.Builtins
alias
Der Satz zulässiger Zeichen in Aliasnamen ist nicht in allen Shells gleich. Ich denke, es ist das gleiche wie für Funktionen (siehe oben).
builtin
Ksh93 hat einen eingebauten Befehl
builtin
, führt jedoch keinen Namen als eingebauten Befehl aus. Verwenden Siecommand
diese Option, um Aliase und Funktionen zu umgehen. Dies ruft ein eingebautes auf, falls eines vorhanden ist, andernfalls einen externen Befehl (Sie können dies mit vermeidenPATH= command error_out_if_this_is_not_a_builtin
).caller
Dies ist bash-spezifisch. Sie können einen ähnlichen Effekt mit bekommen
.sh.fun
,.sh.file
und.sh.lineno
in ksh93. In mksh gibt es endlichLINENO
.declare
,local
,typeset
declare
ist ein bash-spezifischer Name für ksh'stypeset
. Verwendungtypeset
: Es funktioniert auch in Bash.Mksh definiert
local
als Alias fürtypeset
. In ksh93 müssen Sietypeset
einen Alias verwenden (oder definieren).Mksh hat keine assoziativen Arrays (sie sind für eine noch nicht veröffentlichte Version vorgesehen).
Ich glaube nicht, dass es
typeset -t
in ksh ein genaues Äquivalent zu bashs (Trace-Funktion) gibt.cd
Ksh93 hat nicht
-e
.echo
Ksh93 und mksh verarbeiten die Optionen
-e
und-n
wie in bash. Mksh versteht auch-E
, dass ksh93 es nicht als Option behandelt. Die Backslash-Erweiterung ist in ksh93 standardmäßig deaktiviert, in mksh standardmäßig aktiviert.enable
Ksh bietet keine Möglichkeit, integrierte Befehle zu deaktivieren. Um eine integrierte Funktion zu vermeiden, suchen Sie den Pfad des externen Befehls und rufen Sie ihn explizit auf.
exec
Ksh93 hat
-a
aber nicht-l
. Mksh hat keine.export
Weder ksh93 noch mksh haben
export -n
. Verwenden Sietypeset +x foo
stattdessen, es funktioniert in bash und ksh.Ksh exportiert keine Funktionen durch die Umgebung.
let
let
ist das gleiche in bash und ksh.mapfile
,readarray
Dies ist eine Bash-spezifische Funktion. Sie können
while read
Schleifen oder Befehlssubstitution verwenden, um eine Datei zu lesen und in ein Array von Zeilen aufzuteilen. Pass auf dich aufIFS
und globbing. Hier ist das Äquivalent vonmapfile -t lines </path/to/file
:printf
printf
ist sehr ähnlich. Ich denke, ksh93 unterstützt alle Formatanweisungen von bash. mksh unterstützt nicht%q
oder%(DATE_FORMAT)T
; Bei einigen Installationenprintf
ist kein mksh integriert und ruft stattdessen den externen Befehl auf.printf -v VAR
ist bash-spezifisch, ksh druckt immer auf Standardausgabe.read
Einige Optionen sind bash-spezifisch, einschließlich aller Optionen für readline. Die Optionen
-r
,-d
,-n
,-N
,-t
,-u
sind identisch in bash, ksh93 und mksh.readonly
Sie können eine Variable in Ksh93 und mksh mit derselben Syntax als schreibgeschützt deklarieren. Wenn es sich bei der Variablen um ein Array handelt, müssen Sie sie zuerst zuweisen und dann schreibgeschützt machen
readonly VAR
. Funktionen können in ksh nicht schreibgeschützt werden.set
,shopt
Alle Optionen für
set
undset -o
sind POSIX- oder ksh-Funktionen.shopt
ist bash-spezifisch. Viele Optionen betreffen ohnehin die interaktive Nutzung. Informationen zu Auswirkungen auf das Globbing und andere Funktionen, die durch einige Optionen aktiviert werden, finden Sie im Abschnitt „Optionen“ weiter unten.source
Diese Variante von
.
existiert auch in ksh.source
Durchsucht in bash und mksh das aktuelle Verzeichnis nachPATH
, in ksh93 ist es jedoch genau das Äquivalent von.
.trap
Das
DEBUG
Pseudosignal ist in mksh nicht implementiert. In ksh93 gibt es eine andere Möglichkeit, Informationen zu melden. Weitere Informationen finden Sie im Handbuch.type
In ksh
type
ist ein Alias fürwhence -v
. Gibt in mkshtype -p
nicht den Pfad zur ausführbaren Datei aus, sondern eine für Menschen lesbare Nachricht. Sie müssenwhence -p COMMAND
stattdessen verwenden.Optionen
shopt -s dotglob
- Punktdateien beim Globbing nicht ignorierenUm die
dotglob
Option in ksh93 zu emulieren , können Sie festlegenFIGNORE='@(.|..)'
. Ich glaube nicht, dass es so etwas in mksh gibt.shopt -s extglob
- ksh erweiterte Glob-MusterDie
extglob
Option ist in ksh effektiv immer aktiviert.shopt -s failglob
- Fehler aus, wenn ein Glob-Muster mit nichts übereinstimmtIch glaube nicht, dass dies in mksh oder ksh93 existiert. Dies geschieht in zsh (Standardverhalten, sofern nicht festgelegt
null_glob
odercsh_null_glob
festgelegt).shopt -s globstar
-**/
rekursives GlobbingKsh93 hat rekursives Globbing mit
**/
, aktiviert mitset -G
. Mksh hat kein rekursives Globbing.shopt -s lastpipe
- Führen Sie den letzten Befehl einer Pipeline in der übergeordneten Shell ausKsh93 führt immer den letzten Befehl einer Pipeline in der übergeordneten Shell aus, für die in bash die
lastpipe
Option festgelegt werden muss. Mksh führt immer den letzten Befehl einer Pipeline in einer Subshell aus.shopt -s nocaseglob
,shopt -s nocasematch
- Muster ohne Berücksichtigung der Groß- und KleinschreibungMksh hat keinen Mustervergleich, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. Ksh93 unterstützt es Muster für Muster: Stellen Sie dem Muster das Präfix vor
~(i)
.shopt -s nullglob
- Erweitern Sie Muster, die keiner Datei entsprechen, mit einer leeren ListeMksh hat das nicht. Ksh93 unterstützt es Muster für Muster: Stellen Sie dem Muster das Präfix vor
~(N)
.Variablen
Offensichtlich existieren die meisten
BASH_xxx
Variablen nicht in ksh.$BASHPID
kann mit dem teuren, aber tragbarensh -c 'echo $PPID'
Gerät emuliert werden und wurde kürzlich zu mksh hinzugefügt.BASH_LINE
ist.sh.lineno
in ksh93 undLINENO
in mksh.BASH_SUBSHELL
ist.sh.subshell
in ksh93.Mksh und ksh93 beziehen beide die
ENV
beim Start angegebene Datei .EUID
undUID
existieren nicht in ksh93. Mksh nennt sieUSER_ID
undKSH_UID
; es hat nichtGROUPS
.FUNCNAME
undFUNCNEST
existieren nicht in ksh. Ksh93 hat.sh.fun
und.sh.level
. Mitfunction foo { …; }
(keine Klammern!) Deklarierte Funktionen haben ihren eigenen Namen in$0
.GLOBIGNORE
existiert in ksh93, aber mit einem anderen Namen und einer anderen Syntax: Es heißtFIGNORE
und es ist ein einzelnes Muster, keine durch Doppelpunkte getrennte Liste. Verwenden Sie ein@(…|…)
Muster. Ksh's fasstFIGNORE
Bashs mit einer völlig anderen Syntax zusammen.Ksh93 und mksh haben nichts Vergleichbares
HOSTTYPE
,MACHTYPE
undOSTYPE
. NochSHELLOPTS
oderTIMEFORMAT
.Mksh hat
PIPESTATUS
, aber ksh93 nicht.Mksh und ksh93 haben
RANDOM
.quelle
$BASHPID
mit emuliert werdensh -c 'echo $PPID'
? Ich habe es(sh -c 'echo $PPID')
in Bash versucht, aber es gibt mir die gleiche PID wie$$
.Diese Frage ist eher zu weit gefasst.
Sowohl mksh als auch zsh sind Shells, die viele GNU-Bash- spezifische Erweiterungen unterstützen, aber es gibt immer einige, die nicht verstanden werden.
zsh unterstützt mehr Dinge, aber nur in seinem nativen zsh-Modus, der nicht mit POSIX-Shells kompatibel ist (wie GNU bash, AT & T ksh93 , mksh). Außerdem ist mksh viel schlanker und schneller und tragbarer.
Wenn es sich um Ihre Skripte handelt, über die wir sprechen, testen Sie sie im Allgemeinen . (mksh unterstützt noch keine assoziativen Arrays im bash4-Stil. Der Befehl "declare" ist bash-spezifisch, "typeset" ist ein Äquivalent. Ich bin mit zsh nicht vertraut genug, um etwas darüber zu sagen. ksh93 hat kein "local" verwendet aber auch "Schriftsatz" dafür.) Aber wenn es beispielsweise darum geht, ein Debian-System ohne Bash auszuführen, vergessen Sie es. Die Existenz von Bash ist Teil des „Versprechens“ (API / ABI des Systems) und hängt viel davon ab.
Haftungsausschluss: Ich bin der mksh-Entwickler.
quelle
ZSH-Muschelvergleich
Ich bin mit mksh am wenigsten vertraut, daher weiß ich nicht, wo ich nach dieser Antwort suchen soll.
Wenn Sie nach einem sicheren Ersatz für die Shell suchen, unterscheidet sich keine dieser Shells stark von Bash, was den inhärenten Fehler betrifft, den Sie diskutieren.
Eine Sprache wie Perl verarbeitet Eingaben sicherer. Aber auch hier ist die Wartbarkeit von entscheidender Bedeutung. Der Perl-Shell-Ersatz ist nicht sehr gut angenommen. Es liegt in der Verantwortung des Shell-Betreuers, Eingaben sicher zu verarbeiten. Wenn Sie also Skripte schreiben, validieren, validieren, validieren Sie alles! Verwenden Sie Codeverträge, um jedes Mal korrekte Ergebnisse sicherzustellen!
Perl Shell
FSF-Erklärung zu Shell Shock
quelle
Eine Funktion, die in nicht standardmäßig aktiviert
mksh
ist, ist der Shell-Verlauf.In Ihrem
.mkshrc
gerade eingestellten:export HISTFILE=~/.mksh-history
quelle