Your question is a bit rambling. I'll answer what seems to be the central part, on the difference between ksh and bash that you observe.
You have encountered what is probably the #1 incompatibility between ksh and bash when it comes to scripts. ATT ksh (both ksh88 and ksh93) and zsh execute the last (rightmost) command in a pipeline in the parent shell, whereas other shells (Bourne, ash, bash, pdksh, mksh) execute all the commands including the last one in a subshell.
Here is a simple test program:
msg="a subshell"
true | msg="the parent shell"
echo "This shell runs the last command of a pipeline in $msg"
In ATT ksh and zsh, the second assignment to msg
is executed in the parent shell so the effect is visible after the pipeline. In other shells, this assignment is executed in a subshell so the first assignment remains in place in the parent.
A workaround is to execute the rest of the script in the pipeline. This is a common idiom for reading data and doing some processing afterward:
output_some_stuff | {
var=
while IFS= read -r line; do
var=$(process "$line")
done
use "$var"
}
You appear to have run into a ksh bug. I recommend upgrading to a non-buggy version. If that isn't possible, try Stephane Chazelas's workaround. While you can try running your scripts in bash, it is not (and does not pretend to be) a drop-in replacement for ksh; there are plenty of ksh features that bash doesn't have (and vice versa). Bash and ksh are only compatible in their POSIX core and some other central features (in particular arrays, [[ … ]]
, and local variables in functions declared by typeset
).
You could also try zsh, which when invoked as ksh
behaves in a way that's a bit closer to ksh than bash is. You may nonetheless run into incompatibilities.
As of bash 4.2, you can just use a negative index ${myarray[-1]}
to get the last element. You can do the same thing for the second-last, and so on; in Bash:
If the subscript used to reference an element of an indexed array
evaluates to a number less than zero, it is interpreted as relative to
one greater than the maximum index of the array, so negative indices
count back from the end of the array, and an index of -1 refers to the
last element.
The same also works for assignment. When it says "expression" it really means an expression; you can write in any arithmetic expression there to compute the index, including one that computes using the length of the array ${#myarray[@]}
explicitly like ${myarray[${#myarray[@]} - 1]}
for earlier versions.
Best Answer
This simple script shows on my systems (Gnu/Linux and Solaris):
ksh88
limits the size to2^12-1
(4095). (subscript out of range
). Some older releases like the one on HP-UX limit the size to1023
.ksh93
limits the size of a array to2^22-1
(4194303), your mileage may vary.bash
doesn't look to impose any hard-coded limit outside the one dictated by the underlying memory resources available. For example bash uses1.3 GB
of virtual memory for an array size of18074340
.Note: I gave up with
mksh
which was too slow executing the loop (more than one hundred times slower thanzsh
,ksh93
andbash
.)