TL; DR: Für triviale Fälle: Schalten Funktionsdefinition Syntax von den f() compound-command
zu function f { ...; }
. Für komplexe Fälle: Abhängig von ksh93-only (viel flexibler), benutze die folgenden Absurd-Hacks (hart), schreibe streng POSIX-konform (vielleicht hart, unflexibel), schreibe in einer echten Sprache um (aber Shells sind manchmal nett).
Es gibt kein "Linux ksh". Es verhält sich auf allen Systemen gleich und hängt nur von der Version ab, die Sie verwenden.
AIX liefert ein modifiziertes ksh88. ksh88 hatte ein dynamisches Scope-System, ähnlich wie Bash und alle anderen Shells, die Locals unterstützen, aber im Gegensatz zu ksh93. Damit Einheimische unter ksh93 arbeiten können, müssen Sie die "moderne" function name { ; }
-Syntax anstelle der POSIX-Syntax verwenden, um Funktionen zu definieren. Dies kann in ksh88 erforderlich sein oder auch nicht, da es nicht dokumentiert ist und es keine Möglichkeit für mich gibt zu testen, da ksh88 proprietäre Software ist und höchstwahrscheinlich nicht einmal für den Betrieb auf moderner x86-Hardware entwickelt wurde.
Wenn das oben genannte korrekt ist und Ihre Skripte für ksh88 geschrieben wurden, genügt es, die Funktionsdefinitionssyntax zu wechseln, damit lokale Variablen zumindest funktionieren. Während jedoch der statische Bereich von ksh93 dem dynamischen Umfang anderer Shells weit überlegen ist, verursacht er ein ernsthaftes Portabilitätsproblem - wahrscheinlich eines der am schwierigsten zu behandelnden in allen Shell-Skripten.
Wenn Sie tragbare Einheimische benötigen, gibt es keine fantastischen Lösungen. Ich habe zwei Techniken entwickelt, die ksh scope "brechen", um mehr wie ksh88/bash/mksh/zsh usw. zu sein.
Das erste funktioniert in nicht gebrochenen POSIX-Shells.
#!/bin/sh
# (Partially) Working shells: dash, posh, bash, ksh93v, mksh, older zsh
# Broken shells: current zsh, busybox sh, non-bleeding edge alpha ksh93, heirloom
f() {
if ! ${_called_f+false}; then
# Your code using "x"
for x; do
printf '%s, ' "$x"
done
else
# This hackishly localizes x to some degree
_called_f= x= command eval typeset +x x 2\>/dev/null \; f '"[email protected]"'
fi
}
# demonstration code
x='outside f'; printf "$x, "; f 1 2 3; echo "$x"
Die zweite Methode funktioniert nur in KSH artigen Schalen und beinhaltet explizit alles durch Bezugnahme vorbei und ausgiebig mit indirection.
#!/usr/bin/env ksh
# bash, ksh93, mksh, zsh
# Breaking things for dash users is always a plus.
# This is crude. We're assuming "modern" shells only here.
${ZSH_VERSION+false} || emulate ksh
${BASH_VERSION+shopt -s lastpipe extglob}
unset -v is_{ksh93,mksh}
case ${!KSH_VERSION} in
.sh.version) is_ksh93= ;;
KSH_VERSION) is_mksh=
esac
function f {
# We want x to act like in dynamic scope shells. (not ksh93)
typeset x
g x
typeset -p x
}
function g {
# Note mksh and bash 4.3 namerefs kind of suck and are no better than eval.
# This makes a local of a pointer to the variable arg of the same name.
# Remember it's up to the programmer to ensure the sanity of any NAME
# passed through an argument.
${is_ksh93+eval typeset -n ${1}=\$1}
typeset y=yojo
# mksh... you fail at printf. We'll try our best anyway.
eval "$(printf %${is_mksh+.s%s=%s%.s }s=%q "$1" ${is_mksh+"${[email protected]}"} "$y")"
}
f
ich entweder von diesen nur empfehlen, wenn Sie einer der wenigen sind, die robuste Bibliothek Code erfordert das Schreiben, die zu tragbar sein muss.
Hallo Ormaaj, vielen Dank für Ihre ausführliche und sehr hilfreiche Antwort. Es scheint so, als hätte ich falsche Erwartungen und mehr zu tun, als ich mir erhofft hatte. Aber jetzt weiß ich zumindest, wie es mit den kommenden Problemen im Migrationsprozess weitergeht. – Cologne2202