是否可以回显到文件中,但在 shell 脚本源中使用缩进?

the*_*fog 8 bash shell-script

如果我有一些嵌套和缩进的语句将多行字符串回显到文件中,则原始 shell(在我的情况下为 bash)中的缩进将被转移到目标文件中。

为了避免这种情况,我从 echo 输出中删除了缩进,但这会丢失我的源代码中的缩进代码格式,例如,

#! /bin/bash

function configure_default_vhost() {

    case "$2" in
        [--production])
              echo "<VirtualHost *:80>
# These lines are "breaking" out of the preffered indenting
redirect 404 /
ErrorDocument 404
</VirtualHost>
" > /etc/apache/sites-availabe/000-default.conf
    esac
}
Run Code Online (Sandbox Code Playgroud)

我的目标是尽可能接近这个:

#! /bin/bash

function configure_default_vhost() {

    case "$2" in
        [--production])
              echo "<VirtualHost *:80>
                    # These lines are aligned with the preffered indenting
                    redirect 404 /
                    ErrorDocument 404
                    </VirtualHost>
                    " > /etc/apache/sites-availabe/000-default.conf
    esac
}
Run Code Online (Sandbox Code Playgroud)

(注意:这个问题已被列为与 HEREDOC 相关问题的可能重复。我不确定回答这个问题的正确位置在哪里,所以我现在把它放在这里(如果不是,请有人知道)。我的问题是关于代码块的缩进,heredoc 只是实现这一点的众多方法之一,实际上 HEREDOC 不是我采用的解决方案。)

cho*_*oba 12

您可以使用带有-修饰符的“此处文档” 。它可以由制表符缩进。您必须从 切换echocat

cat <<-EOF > /etc/apache/sites-availabe/000-default.conf
        <VirtualHost *:80>
        redirect 404 /
        ErrorDocument 404     
        </VirtualHost>
EOF
Run Code Online (Sandbox Code Playgroud)

或者,为了在结果中保留制表符,您可以通过假设sed和缩进 4 个空格来预处理 HERE 文档:

sed 's/^    //' <<EOF
....{
....(------)func () {
....(------)return
....(------)}
....}
EOF
Run Code Online (Sandbox Code Playgroud)

我使用.而不是空格而(------)不是选项卡来显示如何格式化脚本。


Sté*_*las 8

几种做法:

  • printf '%s\n' > "$conf_file" \
      '<VirtualHost *:80>' \
      '  redirect 404 /' \
      '  ErrorDocument 404' \
      '</VirtualHost>'
    
    Run Code Online (Sandbox Code Playgroud)

    如果要扩展转义序列,请替换%s%b

    printf '%b\n' > "$conf_file" \
      '<VirtualHost *:80>' \
      '\tredirect 404 /' \
      '\tErrorDocument 404' \
      '</VirtualHost>'
    
    Run Code Online (Sandbox Code Playgroud)
  • @choroba 的cat <<- EOF方法,但缩进只能用 TAB 字符完成,它们都被删除了。

  • ...
      indent='
      '; cut -b "${#indent}-" << EOF > "$conf_file"
      <VirtualHost *:80>
        redirect 404 /
        ErrorDocument 404     
      </VirtualHost>
    EOF
    
    Run Code Online (Sandbox Code Playgroud)

    (诀窍是$indent保留要修剪的缩进字符数(这一次要注意,缩进必须使用空格字符,而不是制表符))。

  • ...
      cut -d'|' -f2- << EOF > "$conf_file"
      |echo "<VirtualHost *:80>
      |  redirect 404 /
      |  ErrorDocument 404     
      |</VirtualHost>
    EOF
    
    Run Code Online (Sandbox Code Playgroud)

    转义序列不会被扩展,但变量和命令替换会。引用EOF以防止(cut... << 'EOF'例如)。

  • 您还可以根据第一行的缩进修剪缩进:

    show() {
      expand | awk 'NR == 1 {match($0, /^ */); l = RLENGTH + 1}
                    {print substr($0, l)}'
    }
    ...
      show << EOF > "$conf_file"
        <VirtualHost *:80>
          redirect 404 /
          ErrorDocument 404     
        </VirtualHost>
    EOF
    
    Run Code Online (Sandbox Code Playgroud)


Chr*_*her 3

echo与开关一起使用-e(启用反斜杠转义的解释):

#!/bin/bash

function configure_default_vhost() {
    conf_file="/etc/apache/sites-availabe/000-default.conf"
    case "$2" in
        [--production])
            # The ">" overwrites; the ">>" appends. 
            {
                echo -e "<VirtualHost *:80>"
                echo -e "\tredirect 404 /"
                echo -e "\tErrorDocument 404"
                echo -e "</VirtualHost>"
            } > "$conf_file"
    esac
}
Run Code Online (Sandbox Code Playgroud)