如何在CSH中存储变量或回显时保留换行符?

0 投票
1 回答
29 浏览
提问于 2025-04-13 16:59

我有一个 python 脚本,它是通过一个 csh 脚本调用的(我不能使用 bash)。这个 python 脚本会输出带有换行符的字符串,而我把这个输出存储在一个 csh 变量里。但是,一旦我把它存储到变量中,所有的换行符就都没了。下面是这两个脚本:

python 脚本 (pcmd.py)

def main(op):
    if op == "h": # print help
        # below newline character is getting lost
        print ("Help first line\n second line.")
    else:  # print and later execute csh commands
        print ("setenv SOME_ENV_VAR 123; setenv ANOTHER asd")

if __name__ == "__main__":
    import sys
    main(sys.argv[1])

csh 脚本 (pcmd.csh)

# store the py script in a variable
set pcmd="./pcmd.py $*"
# store the output of the first eval command
set output=`eval "$pcmd"`
# if output contains setenv, eval the output (csh commands)
if ( "$output" =~ *setenv* ) then
    eval "${output}"
else # otherwise, print the output
    echo "${output}"  # Issue : losing newline chars, tried echo -e too but of no avail

执行过程

pcmd.csh h
expects: Help first line
second line.

actual: Help first line second line.  # missing newline character

有没有人能指出脚本中缺少的部分?

1 个回答

3

这就是csh的工作方式。根据它的手册:

命令替换是通过用``包裹的命令来表示的。这样的命令输出会在空格、制表符和换行符处被分开,空的部分会被丢弃。输出的内容会被替换到原来的字符串位置。

在双引号(`")内的命令替换会保留空格和制表符;只有换行符会强制分开成新词。最后的单个换行符在任何情况下都不会强制分开成新词。因此,命令替换可能只输出一个单词的一部分,即使命令输出的是一整行。

默认情况下,从6.12版本开始,shell会把命令中的所有换行符和回车符替换为空格。如果取消这个设置(通过取消csubstnonl),换行符会像往常一样分开命令。

我最后一次使用csh是在1980年代中期。我不相信你想做的事情是可能的。csh是一个糟糕的shell,甚至比像Bash这样的POSIX shell还要差。即使你不能使用Bash,难道没有理由可以使用/bin/sh吗?或者更好的是,使用像Fish或Elvish这样的现代shell?

一个(部分)解决方案是使用双引号和数组捕获:

set output=("`$pcmd`")

这会让output成为一个数组变量,每个元素是一行。然后你可以遍历这个数组,构建一个字符串,其中每个元素(行)之间用换行符分隔。注意我省略了eval,因为在你的例子中它并不必要,而且非常危险。之所以称之为“部分”解决方案,是因为连续的换行符会被当作一个换行符处理。

撰写回答