如何将数字数组从bash传递给csh

时间:2013-12-16 23:32:59

标签: arrays bash csh

首先,在我的辩护中:我只使用csh,因为我的小组有一个很多的遗留csh。我们做科学编程;很多人显然学会了在SunOS / Solaris时代使用csh,并且尽管有linux / bash过渡,但并没有放弃,尽管后者的(IMHO明显)优势。其次,如果这是一个常见问题解答,请道歉,但我没有通过SO或谷歌搜索找到答案,我已经投入了一些努力。

话虽如此:

我想从bash驱动一些遗留的csh脚本,作为[重写,删除]后者的第一步。 bash-> csh适用于标量环境变量('envvars'),因为我可以从bash中导出它们并按预期从csh中读取它们。

不是数组,但是...... 直到Chris J. Kiick's answer以下!以下示例更新为包含Kiick的答案及其产生的结果。将以下2个文件放在同一目录中,......

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

...然后,从你的shell,做...

$ /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

3 个答案:

答案 0 :(得分:3)

我不熟悉csh中的数组,但导出似乎很容易:

bash中的

bdom=${BDOM[*]} mday=${MDAY[*]} ${PARTNER_FP}

你不需要“env”命令,bash有内置的。

要将$ bdom变为单词列表而不是单个字符串,请使用()。 在csh:

set bdom_array = ( $bdom )

答案 1 :(得分:1)

bash不允许您导出数组。 (“然而”,虽然它已经很长时间“尚未”。)因此,将数组从bash导出到csh并不存在问题。您也无法将其从bash导出到bash。 (据我所知,从cshcsh也不是。)

也没有一个很好的解决方法。您可以使用printf'%q'格式以eval'的格式打印元素,但每次更改数组时都必须这样做元素,或者至少每次你可能需要将它导入子shell。此外,bash的{​​{1}}不一定以printf csh将理解的格式导出值。

答案 2 :(得分:0)

正如@rici指出的那样,bash不支持导出数组 - 既不支持export也不支持env - 并且没有强大的解决方法。

那就是说,如果你就知道:

  • 数组元素不包含嵌入空格或其他需要转义的字符
  • 数组中不包含恰好是有效的globbing模式的元素(例如,'*')

然后你可以将数组展平为单行,空格分隔的列表,并以这种方式传递它们。

在你的例子中:

array_writer.sh

# export array as word list, i.e.:
# as single-line string with space-separated tokens
export BDOM_LIST="${BDOM[@]}"

array_reader.csh

# Convert word list back into array.
set BDOM=($BDOM_LIST)