gpt4 book ai didi

linux - 文件重定向在 Bash 脚本中失败,但在 Bash 终端中失败

转载 作者:太空狗 更新时间:2023-10-29 12:10:47 26 4
gpt4 key购买 nike

我在以 .sh 结尾的 Bash 脚本中遇到 cmd1 工作但 cmd2 不工作的问题。我已使 Bash 脚本可执行。

此外,我可以从我的 Bash 终端执行 cmd2。我试图制作一个可重现性最低的示例,但我更大的目标是使用命令行参数运行复杂的可执行文件并将输出传递到可能存在或可能不存在的文件(而不是在终端中显示输出)。

将 > 替换为 >> 也会在脚本中产生相同的错误,但不会在终端中产生。

我的 Bash 脚本:

#!/bin/bash 
cmd1="cat test.txt"
cmd2="cat test.txt > a"
echo $cmd1
$cmd1
echo $cmd2
$cmd2

test.txt 在没有引号的两行中有单词“dog”和“cat”。

最佳答案

简答:参见 BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail! .

长答案:shell 在解析命令行的过程结束时扩展变量引用(如 $cmd1 ),之后 它完成了解析重定向(如 > a 应该是) 和引号和转义以及...事实上,它对扩展值所做的唯一事情就是分词(例如,将 cat test.txt > a 视为“cat”,然后是“test.txt”、“>”,最后是“a” ",而不是单个字符串)和通配符扩展(例如,如果 $cmd 扩展为 cat *.txt ,它将用匹配文件列表替换 *.txt 部分)。 (如果变量在双引号中,它会跳过单词拆分和通配符扩展。)

部分由于这个原因,将命令存储在变量中的最佳方式是:不要。那不是他们的目的;变量用于数据,而不是命令。不过,您应该怎么做,取决于您将命令存储在变量中的原因

  • 如果没有真正的理由将命令存储在变量中,那么直接使用命令即可。对于条件重定向,只需使用标准 if声明:

    if [ -f a ]; then
    cat test.txt > a
    else
    cat test.txt
    fi
  • 如果需要一次性定义命令,以后再用;或者想要一遍又一遍地使用相同的命令而不必每次都完整地写出来,使用一个函数:

    cmd2() {
    cat test.txt > a
    }
    cmd2
  • 听起来您可能需要能够根据某些条件定义不同的命令,实际上您也可以使用函数来实现:

    if [ -f a ]; then
    cmd() {
    cat test.txt > a
    }
    else
    cmd() {
    cat test.txt
    }
    fi
    cmd
  • 或者,您可以将命令(没有重定向)包装在一个函数中,然后使用条件来控制它是否重定向:

    cmd() {
    cat test.txt
    }
    if [ -f a ]; then
    cmd > a
    else
    cmd
    fi
  • 也可以将条件重定向包装到函数本身,然后将输出通过管道传递给它:

    maybe_redirect_to() {
    if [ -f "$1" ]; then
    cat > "$1"
    else
    cat
    fi
    }
    cat test.txt | maybe_redirect_to a

    (这创建了一个额外的 cat 进程,它实际上并没有做任何有用的事情,但如果它使脚本更清晰,我认为这是值得的。在这种特殊情况下,您可以最小化杂散的 cat s 通过使用 maybe_redirect_to a < test.txt 。)

  • 作为最后的手段,您可以将命令字符串存储在变量中,并使用 eval解析它。 eval基本上从头开始重新运行 shell 解析过程,这意味着它将识别字符串中的重定向之类的东西。但是eval作为错误磁铁享有当之无愧的声誉,因为它很容易将您认为只是数据的字符串部分视为命令语法,这可能会导致一些非常奇怪(和危险)的错误。

    如果必须使用eval ,至少对变量引用进行双引号,因此它只运行一次解析过程,而不是像不加引号那样运行一次半。这是我的意思的一个例子:

    cmd3="echo '5 * 3 = 15'"
    eval "$cmd3"
    # prints: 5 * 3 = 15
    eval $cmd3
    # prints: 5 [list of files in the current directory] 3 = 15
    # ...unless there are any files with shell metacharacters in their names, in
    # which case something more complicated might happen.

BashFAQ #50讨论其他一些可能的原因和解决方案。请注意,数组方法在这里不起作用,因为在解析重定向后数组也会得到扩展。

关于linux - 文件重定向在 Bash 脚本中失败,但在 Bash 终端中失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45086023/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com