shell 使用带有函数的bash脚本将环境变量作为csh导出到bash

gdrx4gfi  于 2022-11-16  发布在  Shell
关注(0)|答案(1)|浏览(158)

我有一个bash shell脚本,其中包含一个导出环境变量的函数。为了便于说明,我们使用以下示例:

#!/bin/bash

function my_function()
{
    export my_env_var=$1
}

因为整个目的是将变量导出到主shell I source它。
当主shell是bash时,这可以正常工作:

<bash-shell>
> source ~/tmp/my_test.sh
> my_function test
> echo $my_env_var
test

但是其他客户使用csh,如果我在相同的脚本中使用相同的命令,就会出现问题,因为csh不知道函数:-(

<csh-shell>
% source ~/tmp/my_test.sh
Badly placed ()'s

我已经尝试将其 Package 在 Package 器脚本中:

#!/bin/sh
bash -c 'source ~/tmp/my_test.sh; my_function test`
echo my_env_var = $my_env_var

但my_env_var不是以这种方式导出的:

<csh-shell>
% source ~/tmp/my_test2.sh 
my_env_var: Undefined variable.

它在bash shell中的位置(通过将第二个脚本更改为:
一个
我遗漏了什么/做错了什么,所以当从bash调用变量和从csh调用变量时,脚本会导出变量?

6l7fqoea

6l7fqoea1#

Bourne shell和csh不兼容;许多命令是不同的,csh缺少许多特性(它根本没有函数)。另外,迟早会有人使用fish,这仍然是不同的。使一个重要的脚本对两者都有效的唯一方法是编写两次。
也就是说,如果您想设置一些环境变量,那么一般的策略是创建一个输出所需命令的脚本;这可以用 * 任何 * 语言(shell、Python、C);例如:

#!/bin/sh

# ... do work here ...
var="foo"

# Getting the shell in a cross-platform way isn't too easy. This was only tested
# on Linux. Can add a "-c" or "-f" flag if you need cross-platform support.
shell=$(ps -ho comm $(ps -ho ppid $$))

case "$shell" in
    (csh|tcsh)  echo "setenv VAR $var" ;;
    (fish)      echo "set -Ux VAR $var" ;;
    (*)         echo "export VAR=$var"
esac

当您运行它时,它会输出相应的命令:

% ./work
export VAR=foo

% tcsh
> ./work
setenv VAR foo

> fish
martin@x270 ~> ./work
set -Ux VAR foo

要实际设置它,请按如下方式计算输出:

% eval $(./work)
% echo $VAR
foo

% tcsh
> eval `./work`
> echo $VAR
foo

> fish
martin@x270 ~> eval (./work)
martin@x270 ~> echo $VAR
foo

这样做的缺点是信息性消息、警告等也将得到评估;要解决此问题,请确保始终将这些输出到stderr:

echo >&2 "warning: foo"

如果不想运行eval,也可以使用稍微复杂一点的方法,打印VAR=foo,然后创建Bourne和csh Package 器脚本来解析这些行,但是“输出要设置的变量,而不是直接设置它们”是在多个不兼容的shell中工作的通用方法。

相关问题