aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/_notes/bash.html
blob: 367ee0371dc271f084b833e87106bc288a46f5ca (plain) (tree)
1
2
3
4
5
6



                        

                                                  


































































































































                                                                                



                                                                                    



                                     



                                                                                        




                    
---
title: Bash
subtitle: best practices
layout: plain
links:
  - {rel: stylesheet, href: 'assets/css/bash.css'}
features:
  - title: Arrays
    topics:
      - title: Declaration
        do:
          - |
            local -a xs=()
            declare -a xs=()
            local -A xs=()
            declare -A xs=()

            # Works with nounset:
            echo "${#xs[@]}"
        dont:
          - |
            local -a xs
            declare -a xs
            local -A xs
            declare -A xs

            # Doesn't work with nounset:
            echo "${#xs[@]}"
      - title: Expansion
        do:
          - |
            func ${arr[@]+"${arr[@]}"}
        dont:
          - |
            # Doesn't work with nounset:
            func "${arr[@]}"
            # Doesn't work properly with `declare -a arr=('')`:
            func "${arr[@]+"${arr[@]}"}"
      - title: unset
        do:
          - |
            unset -v 'arr[x]'
            unset -v 'arr[$i]'
        dont:
          - |
            # May break due to globbing:
            unset -v arr[x]
            # In addition, possible quoting problem:
            unset -v arr[$i]
            # Doesn't work for some reason:
            unset -v 'arr["x"]'
            unset -v 'arr["]"]'
            # Also rejected:
            unset -v 'arr["$i"]'

            # An insightful discussion on the topic:
            # https://lists.gnu.org/archive/html/help-bash/2016-09/msg00020.html
  - title: errexit
    topics:
      - title: Command substitution
        do:
          - |
            # Without this, bar will be executed w/ errexit disabled!
            shopt -s inherit_errexit

            bar() {
                false
                echo 'should never see this' >&2
            }

            bar_output="$( bar )"
            foo "$bar_output"
        dont:
          - |
            bar() {
                false
                echo 'should never see this' >&2
            }

            # Even with errexit, foo will still get executed.
            # More than that, the script will print 'should never see this'!
            foo "$( bar )"
      - title: Process substitution
        do:
          - |
            shopt -s lastpipe

            command | while IFS= read -r line; do
                process_line "$line"
            done
        dont:
          - |
            # Without lastpipe, you cannot pipe into read:
            command | while IFS= read -r line; do
                process_line "$line"
            done
          - |
            # errexit doesn't work here no matter what:
            while IFS= read -r line; do
                process_line "$line"
            done < <( command )
            echo 'should never see this'
          - |
            # This would break if $output contains the \0 byte:
            output="$( command )"

            while IFS= read -r line; do
                process_line "$line"
            done <<< "$output"
      - title: Functions
        do:
          - |
            foo() {
                false
                echo 'should never see this' >&2
            }

            foo
            echo ok
        dont:
          - |
            # foo will still print 'should never see this'.
            if foo; then
                echo ok
            fi

            # Same below.
            foo && echo ok
            foo || echo ok
---
{% for feature in page.features %}
  <h2>{{ feature.title }}</h2>
  {% for topic in feature.topics %}
    <h3>{{ topic.title }}</h3>
    <div class="row">
      <div class="col-md-6">
        {% for guide in topic.do %}
          <div class="pre_container pre_do">
            {% highlight bash %}{{ guide }}{% endhighlight %}
            <div class="pre_mark"><span class="glyphicon glyphicon-ok"></span></div>
          </div>
        {% endfor %}
      </div>
      <div class="col-md-6">
        {% for guide in topic.dont %}
          <div class="pre_container pre_dont">
            {% highlight bash %}{{ guide }}{% endhighlight %}
            <div class="pre_mark"><span class="glyphicon glyphicon-remove"></span></div>
          </div>
        {% endfor %}
      </div>
    </div>
  {% endfor %}
{% endfor %}