如何cat&lt; <eof>&gt;一个包含代码的文件?</eof>

时间:2014-03-27 19:45:02

标签: linux unix sh heredoc

我想使用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

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

5 个答案:

答案 0 :(得分:110)

你只需要一个微小的改变;在<<之后单引号此文档分隔符。

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从中读取输入   当前源直到一行只包含分隔符(没有   可见尾随空白)。所有读到的那一行都是   然后用作命令的标准输入。

     

here-documents的格式为:

      <<[-]word
              here-document
      delimiter
     

没有参数扩展,命令替换,算术扩展,   或者对word执行路径名扩展。如果单词中有任何字符   引用,分隔符是单词引用删除的结果,和   here-document中的行未展开。 如果是的话   如果没有引用,here-document的所有行都会受到参数的影响   扩展,命令替换和算术扩展。在里面   后一种情况,字符序列\被忽略,并且   必须用来引用字符\,$和`。

答案 1 :(得分:18)

或者,使用您的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

答案 2 :(得分:9)

这应该有效,我只是测试了它并且按预期工作:没有扩展,替换,或者你发生了什么。

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 ...'

此外,值得注意的是,当使用heredocs时,例如<< 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"

答案 3 :(得分:1)

带有 <<EOF>> 的 cat 将创建内容或将内容附加到现有文件中,不会覆盖。而带有 <<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

答案 4 :(得分:0)

我知道这是一个有两年历史的问题,但这对于那些寻找“方法”的人来说是一个快速的答案。

如果您不想在任何内容两边加上引号,则可以简单地将一个文本块写入文件中,并转义要导出为文本的变量(例如,用于脚本中)而不必转义您要导出为变量的值。

#!/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} =“字符串”输出到控制台“到控制台