TL; DR: Per i casi banali: accendere la sintassi definizione della funzione f() compound-command
-function f { ...; }
. Per i casi complessi: dipende da ksh93-only (molto più flessibile), usa i seguenti assurdi hack (hard), riscritto per essere rigorosamente POSIX conforme (forse difficile, inflessibile), riscrivere in un linguaggio reale (ma le shell a volte sono belle).
Non c'è "Linux ksh". Si comporta allo stesso modo su tutti i sistemi e dipende solo dalla versione che stai utilizzando.
AIX invia un ksh88 modificato. ksh88 aveva un sistema di scope dinamico, simile a Bash e tutte le altre shell che supportano i locali, ma a differenza di ksh93. Affinché la gente del posto possa lavorare sotto ksh93, è necessario utilizzare la sintassi "moderna" function name { ; }
, anziché la sintassi POSIX per definire le funzioni. Questo può essere o non essere richiesto in ksh88, in quanto non è documentato e non c'è modo per me di testare, dato che ksh88 è un software proprietario e molto probabilmente non è nemmeno costruito per funzionare su hardware x86 moderno.
Se quanto sopra è corretto, e i vostri script sono stati scritti per ksh88, semplicemente passare sintassi definizione di funzione è sufficiente per le variabili locali ad almeno la funzione. Tuttavia, sebbene lo scope statico di ksh93 sia di gran lunga superiore all'ambito dinamico di altre shell, causa un serio problema di portabilità, probabilmente uno dei più difficili da risolvere in tutti gli script di shell.
Se avete bisogno di locali portatili, non ci sono soluzioni fantastiche. Mi è venuta in mente due tecniche che "break" scope ksh essere più come ksh88/bash/mksh/zsh ecc
Le prime opere in gusci non-rotto POSIX.
#!/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"
Il secondo metodo funziona solo in gusci ksh-like e coinvolge passando esplicitamente tutto per riferimento e utilizzando indiretto ampiamente.
#!/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
vi consiglio solo uno di questi se sei uno dei pochi che richiede la scrittura di codice robusto libreria che deve essere troppo portatile.
Ciao Ormaaj, la ringrazio molto per la tua risposta dettagliata e MOLTO utile. Sembra che avessi aspettative false e altro da fare di quanto speravo. Ma ora so come procedere nei prossimi problemi nel processo di migrazione. – Cologne2202