用空格缩进heredocs

IBP*_*BPX 31 bash spaces heredoc indentation

对于我所从事的个人开发和项目,我们使用四个空格而不是制表符.但是,我需要使用heredoc,我不能在不打破缩进流的情况下这样做.

我能想到的唯一可行的方法是:

usage() {
    cat << '    EOF' | sed -e 's/^    //';
    Hello, this is a cool program.
    This should get unindented.
    This code should stay indented:
        something() {
            echo It works, yo!;
        }
    That's all.
    EOF
}
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

如果这属于Unix/Linux Stack Exchange,请告诉我.

che*_*ner 40

(如果你使用bash4,滚动到最后我认为是纯shell和可读性的最佳组合.)

对于shell脚本,使用选项卡不是首选项或样式; 这就是语言的定义方式.

usage () {
?# Lines between EOF are each indented with the same number of tabs
?# Spaces can follow the tabs for in-document indentation
?cat <<-EOF
??Hello, this is a cool program.
??This should get unindented.
??This code should stay indented:
??    something() {
??        echo It works, yo!;
??    }
??That's all.
?EOF
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是完全避免使用此处的文档,代价是必须使用更多的引号和行继续:

usage () {
    printf '%s\n' \
        "Hello, this is a cool program." \
        "This should get unindented." \
        "This code should stay indented:" \
        "    something() {" \
        "        echo It works, yo!" \
        "    }" \
        "That's all."
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意放弃POSIX兼容性,则可以使用数组来避免显式行继续:

usage () {
    message=(
        "Hello, this is a cool program."
        "This should get unindented."
        "This code should stay indented:"
        "    something() {"
        "        echo It works, yo!"
        "    }"
        "That's all."
    )
    printf '%s\n' "${message[@]}"
}
Run Code Online (Sandbox Code Playgroud)

下面再次使用here文档,但这次使用bash4的readarray命令来填充数组.参数扩展负责从每个谎言的开头移除固定数量的空格.

usage () {
    # No tabs necessary!
    readarray message <<'    EOF'
        Hello, this is a cool program.
        This should get unindented.
        This code should stay indented:
            something() {
                echo It works, yo!;
            }
        That's all.
    EOF
    # Each line is indented an extra 8 spaces, so strip them
    printf '%s' "${message[@]#        }"
}
Run Code Online (Sandbox Code Playgroud)

最后一个变体:您可以使用扩展模式来简化参数扩展.不必计算用于缩进的空格数,只需使用选定的非空格字符结束缩进,然后匹配固定前缀.我用:.(冒号后面的空格是为了便于阅读;可以通过对前缀模式稍作更改来删除它.)

(另外,对于你使用以空格开头的here-doc分隔符的非常好的技巧的一个缺点是它阻止你在here-doc中执行扩展.如果你想这样做,你会有要么使分隔符保持未缩进,要么对你的无标签规则做一个小的例外,并使用<<-EOF一个制表符缩进的结束分隔符.)

usage () {
    # No tabs necessary!
    closing="That's all"
    readarray message <<EOF
       : Hello, this is a cool program.
       : This should get unindented.
       : This code should stay indented:
       :      something() {
       :          echo It works, yo!;
       :      }
       : $closing
EOF
    shopt -s extglob
    printf '%s' "${message[@]#+( ): }"
    shopt -u extglob
}
Run Code Online (Sandbox Code Playgroud)