2014-12-04 31 views
1

我在使用输出重定向时发现了csh的这种非常奇怪的行为。 我有以下脚本:令人费解的csh重定向行为

#! /bin/csh 
set dirs = "." 
set files = "`find "'"$dirs"'" -type f |& grep -v '^find: '`" 
echo "-----------WITH &-----------------------" 
echo "ARRAY:" $files 
echo "FIRST ELEMENT FROM ARRAY1:" $files[1] 

set files2 = "`find "'"$dirs"'" -type f`" 
echo "------------WITHOUT &-----------------------" 
echo "ARRAY2" $files2 
echo "FIRST ELEMENT SECOND ARRAY" $files2[1] 

现在,如果你运行它,一切正常。结果是:

-----------WITH &----------------------- 
ARRAY: ./.netscape/preferences.js ... 
FIRST ELEMENT FROM ARRAY1: ./.netscape/preferences.js 
------------WITHOUT &----------------------- 
ARRAY2 ./.netscape/preferences.js ... 
FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js 

但是当我运行像这样的csh -x test.csh(这是更大的脚本的一部分,所以我必须以某种方式调试它)我得到这样的:

set dirs = . 
set files = `find "$dirs" -type f |& grep -v '^find: '` 
grep -v ^find: 
echo -----------WITH &----------------------- 
-----------WITH &----------------------- 
echo ARRAY: find . -type f ./.netscape/preferences.js ... 
ARRAY: find . -type f ./.netscape/preferences.js ... 
echo FIRST ELEMENT FROM ARRAY1: find . -type f 
FIRST ELEMENT FROM ARRAY1: find . -type f    <----WHY? 
set files2 = `find "$dirs" -type f` 
find . -type f 
echo ------------WITHOUT &----------------------- 
------------WITHOUT &----------------------- 
echo ARRAY2 ./.netscape/preferences.js ... 
ARRAY2 ./.netscape/preferences.js ... 
echo FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js 
FIRST ELEMENT SECOND ARRAY ./.netscape/preferences.js 

现在,当调试时这会中断脚本。我觉得这种行为相当令人费解。有人可以解释为什么发生这种情况,以及如何避免它?

(。请勿张贴我不应该使用CSH无用的意见,认为它是垃圾我知道,但我的大学那种力量我使用它)

编辑:我所做的一切的建议由约翰C.我的输出是不同的。

bash2-2.05a$ csh -x test.csh 2>catch_stderr 
-----------WITH &----------------------- 
ARRAY: find . -type f ./test.csh ./ff.csh ./ff ./catch_stderr 
FIRST ELEMENT FROM ARRAY1: find . -type f 
------------WITHOUT &----------------------- 
ARRAY2 ./test.csh ./ff.csh ./ff ./catch_stderr 
FIRST ELEMENT SECOND ARRAY ./test.csh 

bash2-2.05a$ cat catch_stderr 
set dirs = . 
set files = `find "$dirs" -type f |& grep -v '^find: '` 
grep -v ^find: 
echo -----------WITH &----------------------- 
echo ARRAY: find . -type f ./test.csh ./ff.csh ./ff ./catch_stderr 
echo FIRST ELEMENT FROM ARRAY1: find . -type f 
set files2 = `find "$dirs" -type f` 
find . -type f 
echo ------------WITHOUT &----------------------- 
echo ARRAY2 ./test.csh ./ff.csh ./ff ./catch_stderr 
echo FIRST ELEMENT SECOND ARRAY ./test.csh 
+2

哪所大学?他们真的迫使你使用它,还是仅仅将它作为默认的交互式shell提供? – 2014-12-04 11:32:00

+0

那么他们给我们两个选项使用CSH或BASH的一些古代版本。但是,如果你选择bash,那么你是独立的,因为讲座和练习中的每个例子都以csh解释。我不想给我的大学命名。 – J91321 2014-12-04 11:41:51

+0

-x将它的输出发送到stderr。我认为你只是看到stdout和stderr混乱了一点。 – 2014-12-04 12:18:13

回答

1

变量-x也适用于subshel​​l。

因此,当子shell `find "'"$dirs"'" -type f |& grep -v '^find: '`得到执行时,它会将find . -type f回显到stderr上(这不会被2>不知道为什么,但它不在我的情况中)然后执行它,但是| &结合了stderr和stdout,并且该组合在脚本中被替换。因此find . -type f最终成为数组$文件中的第一个元素。

解决方案在使用| &在`` csh是非常棘手的。

约翰C也是对的。这实际上指出了我的正确方向。所以我提出了他的答案。他的bash可能会捕获子shell中的输出,所以我认为这两种输出都可能发生。他的输出当然是想要的行为。

1

当您运行csh -x时,它会将每个命令回显到stderr。 如果打开-x和运行这样的脚本....

>sh 
sh-3.2$ csh -x test.csh 2>catch_stderr 
-----------WITH &----------------------- 
ARRAY: ./ff ./ff.csh ./test.csh 
FIRST ELEMENT FROM ARRAY1: ./ff 
------------WITHOUT &----------------------- 
ARRAY2 ./ff ./ff.csh ./test.csh 
FIRST ELEMENT SECOND ARRAY ./ff 

sh-3.2$ cat catch_stderr 
set dirs = . 
set files = `find "$dirs" -type f |& grep -v '^find: '` 
find . -type f 
grep -v ^find: 
echo -----------WITH &----------------------- 
echo ARRAY: ./ff ./ff.csh ./test.csh 
echo FIRST ELEMENT FROM ARRAY1: ./ff 
set files2 = `find "$dirs" -type f` 
find . -type f 
echo ------------WITHOUT &----------------------- 
echo ARRAY2 ./ff ./ff.csh ./test.csh 
echo FIRST ELEMENT SECOND ARRAY ./ff 

(stderr重定向到一个文件),它会表现得同样的方式,因为它没有-x一样。 然后,您可以查看文件catch_stderr以查看跟踪信息。当他们俩一起出来时,他们可以彼此混淆。

+0

请纠正我,如果我错了。你说如果我运行'csh -x script.csh 2> catch_stderr',它应该给我在catch_stderr中的输出,就像运行'csh script.csh'一样吗?因为如果我这样做,它仍然会将该查找作为catch_stderr中该数组的第一个值回显。 – J91321 2014-12-04 16:22:30

+0

嗯看起来像csh不会让你做stderr重定向。首先尝试启动bash shell,然后按照我的说明运行脚本,然后您会看到我想要解释的效果。在运行之前,csh -x回应每个命令。当你在一行中有多个命令时,它将在单独的一行上回显每个单独的命令。这一切都与脚本的常规标准输出混淆在一起。 – 2014-12-04 21:38:28

+0

我确实尝试过,没有相同的结果。让我们假设在两个回声之后,我将添加'echo head -n 1 J91321 2014-12-05 08:06:01