Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
876 views
in Technique[技术] by (71.8m points)

bash - Indenting heredocs with spaces

For personal development and projects I work on, we use four spaces instead of tabs. However, I need to use a heredoc, and I can't do so without breaking the indention flow.

The only working way to do this I can think of would be this:

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
}

Is there a better way to do this?

Let me know if this belongs on the Unix/Linux Stack Exchange instead.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

(If you are using bash 4, scroll to the end for what I think is the best combination of pure shell and readability.)

For shell scripts, using tabs is not a matter of preference or style; it's how the language is defined.

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
}

Another option is to avoid a here document altogether, at the cost of having to use more quotes and line continuations:

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

If you are willing to forego POSIX compatibility, you can use an array to avoid the explicit line continuations:

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
' "${message[@]}"
}

The following uses a here document again, but this time with bash 4's readarray command to populate an array. Parameter expansion takes care of removing a fixed number of spaces from the beginning of each lie.

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[@]#        }"
}

One last variation: you can use an extended pattern to simplify the parameter expansion. Instead of having to count how many spaces are used for indentation, simply end the indentation with a chosen non-space character, then match the fixed prefix. I use :. (The space following the colon is for readability; it can be dropped with a minor change to the prefix pattern.)

(Also, as an aside, one drawback to your very nice trick of using a here-doc delimiter that starts with whitespace is that it prevents you from performing expansions inside the here-doc. If you wanted to do so, you'd have to either leave the delimiter unindented, or make one minor exception to your no-tab rule and use <<-EOF and a tab-indented closing delimiter.)

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
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...