在脚本中看不到脚本中的变量(csh、tcsh)
variable in a script is not seen inside the script (csh, tcsh)
我想设置一个指示目录的变量,并用它来访问该目录中的文件。
所以我写了一个简单的脚本(注意我没有把#!/bin/csh放在前面)
文件测试:
set dir1=/tmp
ls -l $dir1
我做了 chmod +x test
和 运行 test
但它只显示我的当前目录,就像 $dir1 只是空的。我尝试使用 {XX} 无济于事。
而且我想在不使用 #!/usr/bin/env tcsh 或 #!/bin/csch 或 #!/bin/tcsh 的情况下执行此操作。不可能吗? (我不想开始一个新的 shell 但使用相同的别名和其他以前的环境变量等)
怎么了?我在 tcsh 中这样做。
添加
后来才知道
dir1=/tmp
ls $dir1
就是答案。
您应该将 shebang 添加到您的脚本中以强制使用 tcsh
否则将使用默认的 shell!!!
并且您的变量 definition/assignation 语法可能无法按预期工作!
将以下第一行添加到您的脚本中
#!/usr/bin/env tcsh
简短回答:根据您的评论,您需要使用 source
命令 运行 脚本(请参阅@ghoti 的评论)。
长答案:运行 shell 脚本有多种不同的方法,运行 脚本的不同含义。
运行 脚本的通常首选方法是让脚本以 shebang (#!
) 行开始,指定用于它的解释器 (/bin/sh、/bin/bash、等),然后将脚本放在路径中的目录中并按名称执行它,或者将脚本的路径指定为命令(请注意,./scriptname
是一个特殊情况,路径为 "right here").
使用此方法,创建指定解释器的子进程 运行 并执行脚本。由于脚本在子进程中执行,因此其中设置的环境变量之类的东西不会影响它来自 运行 的 shell 的环境(即设置 dir1=/tmp
仅适用于脚本,不适用于完成后)。
如果脚本没有 shebang,您也可以按名称或路径 运行 脚本。这也创建了一个子进程 运行ning 一些解释器(这有点胡说八道)。没有充分的理由这样做;使用 shebang。
您可以通过显式调用解释器来 运行 脚本,如 sh /path/to/script
、bash /path/to/script
或 csh /path/to/script
。请注意,如果脚本在当前目录中,则不需要完整路径;它的名字就足够了。这也是子进程中的脚本,但使用指定的解释器(如果有,则忽略 shebang 行)。
如果您指定了错误的解释器(例如,将 sh
用于使用 bash-only 功能的脚本),这个有时会引起麻烦,并且只有在某些事情阻止您使用第一个选项。
最后,您可以使用 source
命令 运行 脚本(例如 source /path/to/script
或 source scriptname
如果它在当前目录中)。与其他的不同,这不会创建子流程;它告诉当前 shell 从文件中执行命令。这意味着脚本最好用适合您当前 shell 的正确语法编写;如果您 source
来自 csh 或 tcsh 的 bash 或 sh 脚本,它不会顺利进行。这也意味着 shebang(如果有的话)被忽略了。
如果您希望脚本中的环境变量定义在您 运行 中的 shell 脚本中可用,这是唯一的方法。 (好吧,除了在类似 sh 的 shells 中你可以使用 .
命令,因为它是 source
的同义词。)
由于当脚本为 source
d 时,任何 shebang 行都会被忽略,您可以包含或不包含它。我倾向于在应该是 sourced, either giving the correct interpreter as a hint to users, or using a
#!/bin/echoshebang to print a message if someone tries to run the script without
source`:
的脚本中添加 shebang
#!/bin/echo source this script from csh: source
...这有点像 hack,因为 /bin/echo
不是解释器;但它将 运行 命令 /bin/echo source this script from csh: source /path/to/script
至少将用户指向正确的方向。请注意,这不能防止有人用 sh
、bash
等
覆盖 shebang
顺便说一句,关于不兼容命令的其他一些注意事项:正如我所说,set
在 sh-like 和 csh-like shells 中做完全不同的事情。在 csh-like shells 中,您使用 set var=value
分配变量,但在 sh-like shells set
中设置脚本的位置参数(</code>,<code>
, 等等),因此 set var=value
将 </code> 设置为字符串 "var=value"。另外,在您的回答中,您使用了 <code>dir
命令——这根本不是一个 unix 命令,它是一个 DOS 命令;这表明您 运行 将这些脚本置于 Windows 下,在这种情况下,还有其他 class 潜伏的潜在兼容性混淆。
注意 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%
对
1% setenv foo bar
2% echo $foo
bar
3% csh
1% echo $foo
bar
2%
在第一个示例中,set
命令创建了一个 shell 变量,该变量仅在设置它的 shell 的上下文中可见。在第二个示例中,setenv
命令创建了一个 environment 变量,该变量被传递给 subshell.
请注意,在脚本 中通过任一方法设置变量 将不允许将该变量传递回调用 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%
查看 man tcsh
的 History substitution
部分,了解其工作原理。
如果您尝试构建一个依赖于传递回父级 shell 的信息的解决方案,请使用不同的 shell,或者在您的命令中使用带标准输出的反引号替换写,连同别名。
我想设置一个指示目录的变量,并用它来访问该目录中的文件。
所以我写了一个简单的脚本(注意我没有把#!/bin/csh放在前面)
文件测试:
set dir1=/tmp
ls -l $dir1
我做了 chmod +x test
和 运行 test
但它只显示我的当前目录,就像 $dir1 只是空的。我尝试使用 {XX} 无济于事。
而且我想在不使用 #!/usr/bin/env tcsh 或 #!/bin/csch 或 #!/bin/tcsh 的情况下执行此操作。不可能吗? (我不想开始一个新的 shell 但使用相同的别名和其他以前的环境变量等)
怎么了?我在 tcsh 中这样做。
添加
后来才知道
dir1=/tmp
ls $dir1
就是答案。
您应该将 shebang 添加到您的脚本中以强制使用 tcsh 否则将使用默认的 shell!!! 并且您的变量 definition/assignation 语法可能无法按预期工作!
将以下第一行添加到您的脚本中
#!/usr/bin/env tcsh
简短回答:根据您的评论,您需要使用 source
命令 运行 脚本(请参阅@ghoti 的评论)。
长答案:运行 shell 脚本有多种不同的方法,运行 脚本的不同含义。
运行 脚本的通常首选方法是让脚本以 shebang (
#!
) 行开始,指定用于它的解释器 (/bin/sh、/bin/bash、等),然后将脚本放在路径中的目录中并按名称执行它,或者将脚本的路径指定为命令(请注意,./scriptname
是一个特殊情况,路径为 "right here").使用此方法,创建指定解释器的子进程 运行 并执行脚本。由于脚本在子进程中执行,因此其中设置的环境变量之类的东西不会影响它来自 运行 的 shell 的环境(即设置
dir1=/tmp
仅适用于脚本,不适用于完成后)。如果脚本没有 shebang,您也可以按名称或路径 运行 脚本。这也创建了一个子进程 运行ning 一些解释器(这有点胡说八道)。没有充分的理由这样做;使用 shebang。
您可以通过显式调用解释器来 运行 脚本,如
sh /path/to/script
、bash /path/to/script
或csh /path/to/script
。请注意,如果脚本在当前目录中,则不需要完整路径;它的名字就足够了。这也是子进程中的脚本,但使用指定的解释器(如果有,则忽略 shebang 行)。如果您指定了错误的解释器(例如,将
sh
用于使用 bash-only 功能的脚本),这个有时会引起麻烦,并且只有在某些事情阻止您使用第一个选项。最后,您可以使用
source
命令 运行 脚本(例如source /path/to/script
或source scriptname
如果它在当前目录中)。与其他的不同,这不会创建子流程;它告诉当前 shell 从文件中执行命令。这意味着脚本最好用适合您当前 shell 的正确语法编写;如果您source
来自 csh 或 tcsh 的 bash 或 sh 脚本,它不会顺利进行。这也意味着 shebang(如果有的话)被忽略了。如果您希望脚本中的环境变量定义在您 运行 中的 shell 脚本中可用,这是唯一的方法。 (好吧,除了在类似 sh 的 shells 中你可以使用
.
命令,因为它是source
的同义词。)由于当脚本为
的脚本中添加 shebangsource
d 时,任何 shebang 行都会被忽略,您可以包含或不包含它。我倾向于在应该是 sourced, either giving the correct interpreter as a hint to users, or using a
#!/bin/echoshebang to print a message if someone tries to run the script without
source`:#!/bin/echo source this script from csh: source
...这有点像 hack,因为
/bin/echo
不是解释器;但它将 运行 命令/bin/echo source this script from csh: source /path/to/script
至少将用户指向正确的方向。请注意,这不能防止有人用sh
、bash
等 覆盖 shebang
顺便说一句,关于不兼容命令的其他一些注意事项:正如我所说,set
在 sh-like 和 csh-like shells 中做完全不同的事情。在 csh-like shells 中,您使用 set var=value
分配变量,但在 sh-like shells set
中设置脚本的位置参数(</code>,<code>
, 等等),因此 set var=value
将 </code> 设置为字符串 "var=value"。另外,在您的回答中,您使用了 <code>dir
命令——这根本不是一个 unix 命令,它是一个 DOS 命令;这表明您 运行 将这些脚本置于 Windows 下,在这种情况下,还有其他 class 潜伏的潜在兼容性混淆。
注意 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%
对
1% setenv foo bar
2% echo $foo
bar
3% csh
1% echo $foo
bar
2%
在第一个示例中,set
命令创建了一个 shell 变量,该变量仅在设置它的 shell 的上下文中可见。在第二个示例中,setenv
命令创建了一个 environment 变量,该变量被传递给 subshell.
请注意,在脚本 中通过任一方法设置变量 将不允许将该变量传递回调用 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%
查看 man tcsh
的 History substitution
部分,了解其工作原理。
如果您尝试构建一个依赖于传递回父级 shell 的信息的解决方案,请使用不同的 shell,或者在您的命令中使用带标准输出的反引号替换写,连同别名。