Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pass numeric array from bash to csh

Tags:

arrays

bash

csh

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
like image 432
TomRoche Avatar asked Dec 16 '13 23:12

TomRoche


People also ask

What is $@ in bash?

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.

How to access elements of an array in shell script?

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.


2 Answers

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 )
like image 106
Chris J. Kiick Avatar answered Oct 24 '22 06:10

Chris J. Kiick


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.

like image 27
rici Avatar answered Oct 24 '22 06:10

rici