Question

I have a script that need to be run under the (mainly) 3 environment (AIX, Linux [Red hat], sun [nearly no more due to migration]) but always under ksh (not ksh93)

i try to assign value to variable that will work on the 3 environnement, especially resulting of operation like wc -l or sed/awk, ...

due to specification and shell interpretation i can not find a generic code for this. I can use if command to use a specific version of assignation code base on OS but the code need to be understand by each shell

sample of problem (and eval solution) with array declaration

if ${HostLinux}
 then
   eval 'typeset -a aModeTrace=( [0]=false [1]=false [2]=false [3]=false )'
 else
   eval 'set -A aModeTrace false false false false'
 fi

now i have a string to sed and assign to a variable the aix code work with

ThisLine="have a \" and a ' or maybe a \\; and many more other char like any log file could have"
cst_PrintfPipeOS="
"
SampleSize=24
printf '%s%s' "${ThisLine}" "${cst_PrintfPipeOS}" | sed -e "s/^\(.\{${SampleSize}\}\).*/\1/" | read Result

To be easy, i can use the 3 var HostLinux, HostSun and HostAix set to true/false depending running environement (only 1 is true as you could imagine)

1) how to deal with equivalent of | read in linux where the code does not hang on AIX/SUN (code like read Result <<< hang on AIX) 2) using a Result="some code" is dependant of " and ' content and variable surrounding quote

I try to avoid eval on every assignation line (there are more than 1500 lines, imagine the code and the comment and the fun to debug)


Solution used (thanks @Gilles)

use of the ="$( some code without escape specific) liek for a ='some code' (' for back quote)

Result1="`echo '\"'`"
Result2="$(echo '"')"
echo '+Grep'
set | egrep "[R]esult"

->

Result1="
Result2="
+Grep
Result1='"'
Result2='"'

specific not recognize code still need to be "evaluate" via string

Was it helpful?

Solution

Short answer: use ksh93 on all platforms.

The set -A syntax to assign values to an works in all versions of ksh. You only need to use the alternate typeset -a syntax if you run your script under bash. The easiest solution would be to always run your code under ksh. All your platforms have ksh93, so just use that: on Linux, install the ksh package and use it instead of bash. Under ksh93, you can also use a=(aModeTrace false false false false); this also works in bash but not in ksh88 (AIX's ksh is ksh88 but there is also aksh93`).

If you absolutely need a script that's portable between ksh88 and bash, you can put the eval hackery in functions. Only whole array assignment needs to be wrapped in this way, the syntax for access to individual elements, array size and individual element assignment is the same. Use the shell, rather than the operating system, to choose the implementation.

## set_array ARRAY ELEMENT0 ELEMENT1 …
## Set the variable ARRAY to contain the specified elements. Like
## ARRAY=(ELEMENT0 ELEMENT1 …), but also supply a method that works in ksh88.
if [[ -n $BASH_VERSION ]]; then eval '
  set_array () { eval "shift; $1=(\"\$@\")"; }'
else eval '
  set_array () { typeset __set_array_var=$1; shift
    set -A $__set_array_var -- "$@"
  }'
fi

(Note that in ksh, set -A "$@" almost works, but not quite: it fails if the first element of the array begins with a dash.)

String assignments and quoting work in the same way in all shells, there is no portability issue there.

To assign the output of a command, use command substitution (again, it's portable). The only way the output is changed is that trailing newlines are removed (unlike read which expands backslashes and trims leading and trailing whitespace).

Result="$(printf '%s%s' "${ThisLine}" "${cst_PrintfPipeOS}" | 
  sed -e "s/^\(.\{${SampleSize}\}\).*/\1/")"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top