使用 bash 中的变量回显 echo 命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22997675/
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-10 00:47:20  来源:igfitidea点击:

Echoing a echo command with a variable in bash

bashshellvariablesecho

提问by David

Ok, here is one I am struggling with as we speak. Echoing a echo command with a variable.

好的,这是我们说话时我正在努力解决的问题。使用变量回显 echo 命令。

echo "creating new script file."
echo "#!/bin/bash" > $servsfile
echo "read -p "Please enter a service: " ser " >> $servfile
echo "servicetest=`getsebool -a | grep ${ser}` " >> $servfile
echo "if [ $servicetest > /dev/null ];then " >> $servfile
echo "echo "we are now going to work with ${ser}" " >> $servfile
echo "else" >> $servfile
echo "exit 1" >> $servfile
echo "fi" >> $servfile

My goal is create a script using echo commands then run it later. I just need to figure out how to echo echo/read commands while maintaining my variables.

我的目标是使用 echo 命令创建一个脚本,然后再运行它。我只需要弄清楚如何在维护我的变量的同时回显/读取命令。

edit: the variables need to transfer what's inside of them into the new file.

编辑:变量需要将其中的内容传输到新文件中。

采纳答案by mklement0

The immediate problem is you have is with quoting: by using double-quotes, your variable references are instantlyexpanded, which is probably not what you want.

直接的问题是您有引用:通过使用双引号,您的变量引用会立即扩展,这可能不是您想要的。

Use singlequotesinstead - strings inside single quotes are not expanded or interpreted in any way by the shell.

改用引号- 单引号内的字符串不会被 shell 以任何方式扩展或解释。

(If you want selectiveexpansion inside a string - i.e., expand some variable references, but not others - do use double quotes, but prefix the $of references you do notwant expanded with \; e.g., \$var).

(如果你想选择一个字符串中的扩展-即扩大一些变量引用,而不是其他人-做使用双引号,但前缀$你引用的希望与扩大\;例如,\$var)。

However, you're better off using a single here-doc[ument], which allows you to create multi-line stdininput on the spot, bracketed by two instances of a self-chosen delimiter, the opening one prefixed by <<, and the closing one on a line by itself - starting at the very first column; search for Here Documentsin man bashor at http://www.gnu.org/software/bash/manual/html_node/Redirections.html.

但是,您最好使用单个here-doc[ument],它允许您在现场创建多行stdin输入,由两个自行选择的分隔符实例括起来,开头的以 为前缀<<,结束一个单独的一行 - 从第一列开始;搜索Here Documentsman bashhttp://www.gnu.org/software/bash/manual/html_node/Redirections.html

If you quotethe here-doc delimiter(EOFin the code below), variable references are also notexpanded. As @chepner points out, you're free to choose the methodof quoting in this case: enclose the delimiter in single quotes ordouble quotes, oreven simply arbitrarily escape one character in the delimiter with \:

如果引用here-doc分隔符EOF在下面的代码中),变量引用也不会扩展。作为@chepner指出,你可以自由选择的方法,在这种情况下,引用的:在单引号分隔符双引号,或者甚至干脆逃离任意的分隔符以一个字符\

echo "creating new script file."

cat <<'EOF'  > "$servfile"
#!/bin/bash
read -p "Please enter a service: " ser
servicetest=`getsebool -a | grep ${ser}` 
if [ $servicetest > /dev/null ]; then 
  echo "we are now going to work with ${ser}"
else
  exit 1
fi
EOF

As @BruceK notes, you can prefix your here-doc delimiter with -(applied to this example: <<-"EOF") in order to have leading tabsstripped, allowing for indentation that makes the actual content of the here-doc easier to discern. Note, however, that this only works with actual tabcharacters, not leading spaces.

正如@BruceK 所指出的,您可以在 here-doc 分隔符前加上-(应用于此示例: <<-"EOF") 以去除前导制表符,允许缩进使 here-doc 的实际内容更容易辨别。但是请注意,这仅适用于实际的制表符,不适用于前导空格。

Employing this technique combined with the afterthoughts regarding the script's content below, we get (again, note that actual tabchars. must be used to lead each here-doc content line for them to get stripped):

将这种技术与关于下面脚本内容的事后想法相结合,我们得到(再次注意,必须使用实际的制表符来引导每个 here-doc 内容行,以便它们被剥离):

cat <<-'EOF' > "$servfile"
    #!/bin/bash
    read -p "Please enter a service name: " ser
    if [[ -n $(getsebool -a | grep "${ser}") ]]; then 
      echo "We are now going to work with ${ser}."
    else
      exit 1
    fi
EOF

Finally, note that in basheven normal single- or double-quoted strings can span multiple lines, but you won't get the benefits of tab-stripping or line-block scoping, as everythinginside the quotes becomes part of the string.

最后,请注意,bash即使是普通的单引号或双引号字符串也可以跨越多行,但您不会获得制表符剥离或行块范围的好处,因为引号内的所有内容都将成为字符串的一部分。

Thus, note how in the following #!/bin/bashhas to follow the opening 'immediatelyin order to become the first line of output:

因此,请注意以下内容如何#!/bin/bash必须'立即跟随开头才能成为第一行输出:

echo '#!/bin/bash
read -p "Please enter a service: " ser
servicetest=$(getsebool -a | grep "${ser}")
if [[ -n $servicetest ]]; then 
  echo "we are now going to work with ${ser}"
else
  exit 1
fi' > "$servfile"


Afterthoughts regarding the contents of your script:

关于脚本内容的事后思考:

  • The syntax $(...)is preferred over `...`for command substitution nowadays.
  • You should double-quote ${ser}in the grepcommand, as the command will likely break if the value contains embedded spaces (alternatively, make sure that the valued read contains no spaces or other shell metacharacters).
  • Use [[ -n $servicetest ]]to test whether $servicetestis empty (or perform the command substitution directly inside the conditional) - [[ ... ]]- the preferred form in bash- protects you from breaking the conditional if the $servicetesthappens to have embedded spaces; there's NEVER a need to suppress stdout output inside a conditional (whether [ ... ]or [[ ... ]], as no stdout output is passed through; thus, the > /dev/nullis redundant (that said, with a command substitution inside a conditional, stderroutput IS passed through).
  • 现在,该语法$(...)优于`...`命令替换。
  • 您应该${ser}grep命令中用双引号引起来,因为如果值包含嵌入的空格,该命令可能会中断(或者,确保读取的值不包含空格或其他 shell 元字符)。
  • 使用[[ -n $servicetest ]]以测试是否$servicetest是空的(或直接执行条件内的命令替换) - [[ ... ]]-在优选形式bash-保护你从断裂条件,如果$servicetest恰好有嵌入空格; 从来没有必要在条件中抑制 stdout 输出(无论是[ ... ]还是[[ ... ]],因为没有传递 stdout 输出;因此,这> /dev/null是多余的(也就是说,在条件中使用命令替换,传递了stderr输出)。

回答by Mihai

You just need to use single quotes:

您只需要使用单引号:

$ echo "$TEST"
test
$ echo '$TEST'
$TEST

Inside single quotes special characters are not special any more, they are just normal characters.

单引号内的特殊字符不再特殊,它们只是普通字符。

回答by GoinOff

echo "echo "we are now going to work with ${ser}" " >> $servfile

Escape all " within quotes with \. Do this with variables like \$servicetest too:

使用 \ 将所有 " 转义到引号内。也可以使用 \$servicetest 之类的变量执行此操作:

echo "echo \"we are now going to work with ${ser}\" " >> $servfile    
echo "read -p \"Please enter a service: \" ser " >> $servfile
echo "if [ $servicetest > /dev/null ];then " >> $servfile