如何对包含代码的文件执行 cat < < EOF > ?

我想打印代码到一个文件使用 cat <<EOF >>:

cat <<EOF >> brightup.sh
!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
curr=$((curr+406));
echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

但是当我检查文件输出时,我得到了这个:

!/bin/bash
curr=1634
if [  -lt 4477 ]; then
curr=406;
echo   > /sys/class/backlight/intel_backlight/brightness;
fi

我尝试放置单引号,但输出也带有单引号。我如何避免这个问题?

305544 次浏览

这个应该可以,我刚刚测试了一下,它正如预期的那样工作: 没有扩展,替换,或者发生了什么。

cat <<< '
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
curr=$((curr+406));
echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi' > file # use overwrite mode so that you don't keep on appending the same script to that file over and over again, unless that's what you want.

使用以下方法也可行。

cat <<< ' > file
... code ...'

此外,值得注意的是,当使用 herdocs,如 << EOF,替换和变量扩展等发生。所以做这样的事情:

cat << EOF > file
cd "$HOME"
echo "$PWD" # echo the current path
EOF

总是会导致变量 $HOME$PWD的展开。因此,如果您的主目录是 /home/foobar,而当前路径是 /home/foobar/bin,那么 file将如下所示:

cd "/home/foobar"
echo "/home/foobar/bin"

而不是预期的:

cd "$HOME"
echo "$PWD"

或者,使用你的 EOF 标记,你需要引用初始标记,这样扩展就不会被完成:

#-----v---v------
cat <<'EOF' >> brightup.sh
#!/bin/bash
curr=`cat /sys/class/backlight/intel_backlight/actual_brightness`
if [ $curr -lt 4477 ]; then
curr=$((curr+406));
echo $curr  > /sys/class/backlight/intel_backlight/brightness;
fi
EOF

IHTH

您只需要进行最小的更改; 在 <<之后单引号 here-document 分隔符。

cat <<'EOF' >> brightup.sh

或者等效的反斜杠-转义它:

cat <<\EOF >>brightup.sh

如果没有引号,这里的文档将进行变量替换,将计算反勾,等等,就像您发现的那样。

如果您需要展开一些值,但不是全部值,那么您需要单独地转义那些您想要防止的值。

cat <<EOF >>brightup.sh
#!/bin/sh
# Created on $(date # : <<-- this will be evaluated before cat;)
echo "\$HOME will not be evaluated because it is backslash-escaped"
EOF

会产生

#!/bin/sh
# Created on Fri Feb 16 11:00:18 UTC 2018
echo "$HOME will not be evaluated because it is backslash-escaped"

正如 @ Fedorqui所建议的,以下是 man bash的相关章节:

此处文件

这种类型的重定向指示 shell 从 直到只包含分隔符的行为止 后面的空格)可以看到。到该点为止的所有行都是 然后用作命令的标准输入。

此处-文件的格式如下:

      <<[-]word
here-document
delimiter

没有参数展开,指令替代,算术展开, 或路径名扩展在 word 中执行。如果 word 中有任何字符 则分隔符是单词上引号移除的结果,并且 Here-document 中的行没有展开。 < strong > If word is 如果没有引号,则此处文档的所有行都受到参数的限制 扩展、指令替代和算术扩展 后一种情况下,字符序列 \<newline>被忽略,而 \ 必须用于引用字符 \$`

我知道这是一个两年前的问题,但对于那些寻找“如何”的人来说,这是一个快速的答案。

如果你不想在任何东西上加引号,你可以简单地写一个文本块到一个文件中,转义你想要导出为文本的变量(例如在脚本中使用) ,而不是转义你想要导出为变量值的变量。

#!/bin/bash


FILE_NAME="test.txt"
VAR_EXAMPLE="\"string\""


cat > ${FILE_NAME} << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} in ${FILE_NAME}
EOF

将 test.txt 中的“ ${ VAR _ EXAMPLE } = “ string”写入 test.txt

这也可以用来通过省略文件名将文本块输出到具有相同规则的控制台

#!/bin/bash


VAR_EXAMPLE="\"string\""


cat << EOF
\${VAR_EXAMPLE}=${VAR_EXAMPLE} to console
EOF

将输出“ ${ VAR _ EXAMPLE } = “ string”到控制台”

Cat 使用 <<EOF>>将创建或追加内容到现有文件,不会覆盖。而使用 <<EOF>的 cat 将创建或覆盖内容。

cat test.txt
hello


cat <<EOF>> test.txt
> hi
> EOF


cat test.txt
hello
hi


cat <<EOF> test.txt
> haiiiii
> EOF


cat test.txt
haiiiii