具有多个命令和可重入的 BASH 变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1121189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 21:02:52  来源:igfitidea点击:

BASH Variables with multiple commands and reentrant

bashshellcommand

提问by Eric

I have a bash script that sources contents from another file. The contents of the other file are commands I would like to execute and compare the return value. Some of the commands are have multiple commands separated by either a semicolon (;) or by ampersands (&&) and I can't seem to make this work. To work on this, I created some test scripts as shown:

我有一个 bash 脚本,它从另一个文件中获取内容。另一个文件的内容是我想执行和比较返回值的命令。有些命令有多个命令,由分号 (;) 或与号 (&&) 分隔,我似乎无法完成这项工作。为了解决这个问题,我创建了一些测试脚本,如下所示:

test.conf is the file being sourced by test

test.conf 是测试来源的文件

Example-1 (this works), My output is 2 seconds in difference

示例 1(这有效),我的输出相差 2 秒

test.conf

测试配置文件

    CMD[1]="date"

test.sh

测试文件

    . test.conf
    i=2
    echo "$(${CMD[$i]})"
    sleep 2
    echo "$(${CMD[$i]})" 

Example-2 (this does not work) test.conf (same script as above)

示例 2(这不起作用) test.conf(与上面相同的脚本)

    CMD[1]="date;date"

Example-3 (tried this, it does not work either) test.conf (same script as above)

Example-3(试过这个,它也不起作用)test.conf(与上面相同的脚本)

    CMD[1]="date && date"

I don't want my variable, CMD, to be inside tick marks because then, the commands would be executed at time of invocation of the source and I see no way of re-evaluating the variable.

我不希望我的变量 CMD 位于刻度线内,因为这样,命令将在调用源时执行,我看不到重新评估变量的方法。

This script essentially calls CMD on pass-1 to check something, if on pass-1 I get a false reading, I do some work in the script to correct the false reading and re-execute & re-evaluate the output of CMD; pass-2.

该脚本本质上在 pass-1 上调用 CMD 来检查某些内容,如果在 pass-1 上我得到错误读数,我会在脚本中做一些工作来纠正错误读数并重新执行和重新评估 CMD 的输出;通过-2。

Here is an example. Here I'm checking to see if SSHD is running. If it's not running when I evaluate CMD[1] on pass-1, I will start it and re-evaluate CMD[1] again.

这是一个例子。在这里,我正在检查 SSHD 是否正在运行。如果我在 pass-1 评估 CMD[1] 时它没有运行,我将启动它并再次重新评估 CMD[1]。

test.conf

测试配置文件

    CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`

So if I modify this for my test script, then test.conf becomes: NOTE: Tick marks are not showing up but it's the key below the ~ mark on my keyboard.

因此,如果我为我的测试脚本修改它,那么 test.conf 将变为: 注意:没有显示刻度线,但它是我键盘上 ~ 标记下方的键。

    CMD[1]=`date;date` or `date && date`

My script looks like this (to handle the tick marks)

我的脚本看起来像这样(处理刻度线)

    . test.conf
    i=2
    echo "${CMD[$i]}"
    sleep 2
    echo "${CMD[$i]}"

I get the same date/time printed twice despite the 2 second delay. As such, CMD is not getting re-evaluate.

尽管延迟了 2 秒,但我还是打印了两次相同的日期/时间。因此,CMD 不会被重新评估。

采纳答案by Paused until further notice.

First of all, you should never use backticks unless you need to be compatible with an old shell that doesn't support $()- and only then.

首先,除非您需要与不支持的旧外壳兼容,否则永远不应使用反引号$()-只有这样

Secondly, I don't understand why you're setting CMD[1]but then calling CMD[$i]with iset to 2.

其次,我不明白你为什么要设置CMD[1],然后CMD[$i]iset to调用2

Anyway, this is one way (and it's similar to part of Barry's answer):

无论如何,这是一种方式(它类似于巴里的部分答案):

CMD[1]='$(date;date)'    # no backticks (remember - they carry Lime disease)
eval echo "${CMD[1]}"    # or $i instead of 1

回答by Barry Kelly

From the couple of lines of your question, I would have expected some approach like this:

从你的问题的几行来看,我本来希望有这样的方法:

#!/bin/bash

while read -r line; do
    # munge $line
    if eval "$line"; then
        # success
    else
        # fail
    fi
done

Where you have backticks in the source, you'll have to escape them to avoid evaluating them too early. Also, backticks aren't the only way to evaluate code - there is eval, as shown above. Maybe it's evalthat you were looking for?

如果源代码中有反引号,则必须将它们转义以避免过早评估它们。此外,反引号不是评估代码的唯一方法 - 有eval,如上所示。也许这eval就是你要找的?

For example, this line:

例如,这一行:

CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`

Ought probably look more like this:

应该看起来更像这样:

CMD[1]='`pgrep -u root -d , sshd 1>/dev/null; echo $?`'