脚本中没有看到脚本中的变量(csh,tcsh)

时间:2017-11-02 01:59:34

标签: bash csh tcsh

我想设置一个指示目录的变量,并使用它来访问该目录中的文件 所以我写了一个简单的脚本(注意我没有把#!/ bin / csh放在前面)

文件测试:

set dir1=/tmp
ls -l $dir1

我做了chmod +x test并运行了test,但它只显示我当前的目录,如$ dir1只是null。我尝试使用{XX}无济于事。

我想在没有usig#!/ usr / bin / env tcsh或#!/ bin / csch或#!/ bin / tcsh的情况下这样做。这不可能吗? (我不想启动新的shell但使用相同的别名和其他先前的环境变量等。)

有什么问题?我在tcsh中这样做。

ADD

我后来发现了

dir1=/tmp
ls $dir1

就是答案。

3 个答案:

答案 0 :(得分:3)

注意 shell变量之间的区别,它可以交互使用或在脚本中使用但是对于脚本是本地的,而环境变量则成为传递的环境的一部分到脚本调用的程序。

在POSIX(或bash或相关)shell中,您可以使用export内置命令将shell变量转换为环境变量。

在csh / tcsh中,set命令设置shell变量,但setenv命令设置环境变量。设置完成后,您可以像shell变量一样在shell脚本中使用环境变量,但该变量将包含在子shell或您运行的其他程序的环境中。

注意:

1% set foo=bar
2% echo $foo
bar
3% csh
1% echo $foo
foo: Undefined variable.
2%

VS

1% setenv foo bar
2% echo $foo
bar
3% csh
1% echo $foo
bar
2%

在第一个示例中,set命令创建了一个shell变量,该变量仅在设置它的shell的上下文中可见。在第二个示例中,setenv命令创建了一个传递给子shell的 environment 变量。

请注意,通过脚本中的任何方法设置变量将不允许将该变量传递回调用shell,就像使用使用花括号的POSIX shell函数一样。对于csh / tcsh中的那种功能,您可能不得不依赖alias命令。例如,我使用以下别名:

alias go 'cd `dirname \!:*`'

让我这样做:

1% alias go 'cd `dirname \!:*`'
2% go /usr/local/etc/foo.rc
3% pwd
/usr/local/etc
4%

查看History substitution的{​​{1}}部分,了解其工作原理。

如果您正在尝试构建依赖于传递回父shell的信息的解决方案,请使用不同的shell,或者对您编写的命令使用stdout的反引号替换以及别名。

答案 1 :(得分:2)

简短回答:根据您的评论,您需要使用source命令运行脚本(请参阅@ ghoti的文章)。

答案很长:有许多不同的方法来运行shell脚本,对它的运行方式有不同的影响。

  • 运行脚本的正常首选方法是让脚本以shebang(#!)行开头,指定要用于它的解释器(/ bin / sh,/ bin / bash等) ),然后将脚本放在路径中的目录中并按名称执行,或者将脚本的路径指定为命令(请注意./scriptname是此特殊情况,其中路径为“就在这里“)。

    使用此方法,将创建运行指定解释器的子进程并执行该脚本。由于脚本在子进程中执行,因此设置的环境变量之类的东西不会影响它运行的shell的环境(即设置dir1=/tmp仅适用于脚本,而不是在脚本完成后。)

  • 如果脚本没有shebang,您也可以按名称或路径运行脚本。这也创建了一个运行一些解释器的子进程(其中一个是一个crapshoot)。这样做是没有充分理由的;使用shebang。

  • 您可以通过显式调用解释器来运行脚本,如sh /path/to/scriptbash /path/to/scriptcsh /path/to/script。请注意,如果脚本位于当前目录中,则不需要完整路径;它的名字就足够了。这也在子进程中运行脚本,但使用指定的解释器(如果有的话,忽略shebang行)。

    如果您指定了错误的解释器(例如,对于使用仅使用bash的功能的脚本使用sh),这个有时会造成麻烦,并且只有在某些东西阻止您使用第一个选项时才应该使用它。

  • 最后,您可以使用source命令运行脚本(例如source /path/to/scriptsource scriptname,如果它在当前目录中)。与其他人不同,这不会创建子流程;它告诉当前shell从文件中执行命令。这意味着最好用当前shell的正确语法编写脚本;如果你从csh或tcsh {b}或sh脚本source,它就不会顺利。这也意味着shebang(如果有的话)会被忽略。

    如果您希望脚本中的环境变量定义在您运行脚本的shell中可用,则这是唯一的方法。 (好吧,除了类似sh的shell,你可以使用.命令,因为这是source的同义词。)

    由于脚本为source d时会忽略任何shebang行,因此您可以包含它。我倾向于将一个shebang添加到应该是源d, either giving the correct interpreter as a hint to users, or using a#!/ bin / echo shebang to print a message if someone tries to run the script without source`的脚本中:

    #!/bin/echo source this script from csh: source
    

    ...这是一种黑客攻击,因为/bin/echo不是解释者;但它会运行命令/bin/echo source this script from csh: source /path/to/script,它至少指向用户正确的方向。请注意,这并不能防止有人使用shbash等来覆盖shebang。

BTW,关于不兼容命令的其他一些注意事项:正如我所说,set在类似于类似于csh的shell中做了完全不同的事情。在类似csh的shell中,您使用set var=value分配变量,但在类似sh的shell set中设置脚本的位置参数($1$2等),因此{ {1}}将set var=value设置为字符串“var = value”。另外,在你的回答中,你使用$1命令 - 这根本不是一个unix命令,它是一个DOS命令;这表明你在Windows下运行这些脚本,在这种情况下潜伏着另外一类潜在的兼容性混淆。

答案 2 :(得分:1)

您应该将shebang添加到脚本中以强制使用tcsh 否则将使用默认shell! 并且您的变量定义/赋值语法可能无法按预期工作!

将以下第一行添加到您的脚本

#!/usr/bin/env tcsh