Firstly, in my defense: I'm only using csh because my group has a lot of legacy csh. We do scientific programming; a lotta folks apparently learned to use csh back in the SunOS/Solaris days, and didn't give up despite the linux/bash transition, and despite the (IMHO obvious) superiority of the latter. Secondly, apologies if this is a FAQ, but I haven't found an answer via SO or googling generally, and I have devoted some effort to both.
That being said:
I want to drive from bash some legacy csh scripts, as a first step toward [rewriting, removing] the latter. bash->csh works fine for scalar environment variables ('envvars'), in that I can export them from bash and read them from csh as expected.
Not arrays, however ... until Chris J. Kiick's answer below! Following example is updated to include Kiick's answer, and the results it produces. Put the following 2 files in the same directory, ...
array_writer.sh
#!/usr/bin/env bash
### Test writing an array, passing it to csh, and reading it there.
THIS="$0"
THIS_DIR="$(readlink -f $(dirname ${THIS}))"
THIS_FN="$(basename ${THIS})"
MESSAGE_PREFIX="${THIS_FN}:"
ERROR_PREFIX="${MESSAGE_PREFIX} ERROR:"
PARTNER_FN='array_reader.csh'
PARTNER_DIR="${THIS_DIR}"
PARTNER_FP="${PARTNER_DIR}/${PARTNER_FN}"
export YEAR='2007'
# month-related arrays for ${YEAR}
declare -a BDOM=(0 31 59 90 120 151 181 212 243 273 304 334) # 0-based-Julian of first day of each month
declare -a MDAY=(31 28 31 30 31 30 31 31 30 31 30 31) # days in each month, length=12
echo -e "${MESSAGE_PREFIX} YEAR='${YEAR}':"
# start debugging
# use subshell for IFS
( IFS=',' ; echo -e "\tBDOM=${BDOM[*]}" )
( IFS=',' ; echo -e "\tMDAY=${MDAY[*]}" )
# end debugging
### Direct export of arrays fails, but this works!
### Note it actually exports a string: see handling in partner
echo -e "${MESSAGE_PREFIX} about to call ${PARTNER_FP}:\n"
# from https://stackoverflow.com/a/20625229/915044
bdom=${BDOM[*]} mday=${MDAY[*]} ${PARTNER_FP}
if [[ $? -ne 0 ]] ; then
echo -e "\n${ERROR_PREFIX} failed or not found\n"
else
echo -e "\n${MESSAGE_PREFIX} ${PARTNER_FP} returned successfully"
fi
array_reader.csh
#!/bin/csh -f
### Test reading an array written from bash.
set THIS="$0"
# set THISDIR="$(readlink -f $(dirname ${THIS}))" # fails!
set THIS_DIRNAME=`dirname ${THIS}`
set THIS_DIR=`readlink -f ${THIS_DIRNAME}`
set THIS_FN=`basename ${THIS}`
set MESSAGE_PREFIX="${THIS_FN}:"
set ERROR_PREFIX="${MESSAGE_PREFIX} ERROR:"
if ( $?bdom ) then
# Gotta convert passed string into a "real" csh array
set bdom_array = ( $bdom )
echo ${MESSAGE_PREFIX} found export=bdom, size=$#bdom_array":"
printf "\t" # continue on same line
foreach item ( $bdom_array )
printf "%d," $item # ditto
end
echo "" # newline to end the array-printing line
else
echo "${ERROR_PREFIX} no export=bdom"
exit 2
endif
echo "" # separate reports
if ( $?mday ) then
set mday_array = ( $mday )
echo ${MESSAGE_PREFIX} found export=mday, size=$#mday_array":"
printf "\t"
foreach item ( $mday_array )
printf "%d," $item
end
echo "" # newline to end the array-printing line
else
echo "${ERROR_PREFIX} no export=mday"
exit 3
endif
exit 0
... then, from your shell, do ...
$ /path/to/array_writer.sh
array_writer.sh: YEAR='2007':
BDOM=0,31,59,90,120,151,181,212,243,273,304,334
MDAY=31,28,31,30,31,30,31,31,30,31,30,31
array_writer.sh: about to call /path/to/array_reader.csh:
array_reader.csh: found export=bdom, size=12:
0,31,59,90,120,151,181,212,243,273,304,334,
array_reader.csh: found export=mday, size=12:
31,28,31,30,31,30,31,31,30,31,30,31,
array_writer.sh: /path/to/array_reader.csh returned successfully
bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc.
Access Array Elements Similar to other programming languages, Bash array elements can be accessed using index number starts from 0 then 1,2,3…n. This will work with the associative array which index numbers are numeric. To print all elements of an Array using @ or * instead of the specific index number.
I'm not familiar with arrays in csh, but exporting seems easy enough:
in bash:
bdom=${BDOM[*]} mday=${MDAY[*]} ${PARTNER_FP}
You don't need the "env" command, bash has that built in.
To make $bdom into a list of words, instead of a single string, use (). in csh:
set bdom_array = ( $bdom )
bash
doesn't let you export arrays. ("Yet", although it's been "not yet" for a long time.) So it's not that there is a problem exporting arrays from bash
to csh
. You can't export them from bash
to bash
either. (Nor, as far as I know, from csh
to csh
.)
There isn't really a great workaround either. You could use the printf
'%q
' format to print the elements out in a format which could be eval
'd, but you'd have to do that every time you changed an array element, or at least every time you might need to import it into a subshell. Also, bash
's printf
doesn't necessarily export values in a format which csh
's eval
will understand.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With