bash
Contents
Coding style
General
- When in doubt, be consistent.
- This document is no dogma. The specification may be changed if there are good reasons.
Examples
Formatter
shfmt
- shfmt is shell formatter, which supports POSIX Shell, Bash, and mksh.
- Your IDE probably has similar options,
because it will use shfmt in the background.
Install shfmt
1 aptitude install shfmt
vim
Just use gg=G or :Shfmt
Header
- Add a header to the file containing
SHEBANG line #!/path/to/executables args containing the shell, the script has been written for.
#!/usr/bin/env bash
- Searches PATH for executable.
#!/bin/bash
- Author
- Company
- Description
- License
- A header is informational and protects your and others rights.
Shellcheck
- Use shellcheck!
- Adhere to shellcheck. It's gonna make you write better code!
https://docs.gitlab.com/ee/development/shell_scripting_guide/#linting
Indentation with tabs and alignment with spaces
General
- Use tabs for indentation
- No, do not expand tabs
- Adjust tab-width to your preference in your editor
Just as a reminder a tab are 8 spaces.
This leads to earlier line-continuations.
Corresponds to shfmt options
- Use spaces for alignment
:retab! may be necessary before
Corresponds to shfmt options
Example with bash heredoc
Indent switch cases
- Also indent switch cases
Corresponds to shfmt options
- Example case indent (with getopt case handling)
Binary operators and pipelines
- Indent line-continuations with an additional tab to the current depth
Corresponds to shfmt options
- Binary operators and pipelines are continued on a new line (and therefor additionally indented)
- Senseless example just for the purpose of demonstration
Lines
- Maximum line length is 80 characters
- A tab is one char …
- No trailing spaces in the end of line
- Separate blocks with an empty line
VARIABLES
- Variable names are in SCREAMING_CAPITAL_CASE
function_definitions
Function names are snake_case
Keyword function is optional, but has to be used consistently across the file
The double parenthesis () must directly follow the function_name
Use arrays to pass options to a program
- Don't use plain strings
Command grouping and subshells
Bash Command-Grouping with () and {}
i++
for
while
In a while read loop, outer and inner read-commands are fed by the same STDIN. This makes confirmation requests impossible.
round with printf
list of ranges
1 #!/bin/bash
2
3 RANGE_LIST_INPUT="$1"
4 RANGE_INCR="${2:-1}"
5
6 sequ() (
7 local MIN="$1"
8 local INCR="$2"
9 local MAX="$3"
10 echo "for (i = $MIN; i <= $MAX; i+=$INCR) i" | bc -l
11 )
12
13 split_list() {
14 local LIST="$1"
15 local DELIM="${2:-,}"
16 local -a RETURN
17
18 readarray -td "$DELIM" RETURN < <(echo -n "$LIST")
19
20 printf '%s\n' "${RETURN[@]}"
21 }
22
23 expand_range() {
24 local RANGE="$1"
25 local DELIM="${2:--}"
26 local MIN MAX
27 local -a RETURN
28
29 MIN="$(cut -f1 -d"$DELIM" <<< "$RANGE")"
30 if grep -q "$DELIM" <<< "$RANGE"; then
31 MAX="$(cut -f2 -d"$DELIM" <<< "$RANGE")"
32 else
33 MAX="$MIN"
34 fi
35
36 readarray -t RETURN < <(sequ "$MIN" "$RANGE_INCR" "$MAX")
37
38 printf '%s\n' "${RETURN[@]}"
39 }
40
41 expand_range_list() {
42 local RANGE_LIST="$1"
43 local RANGE
44 local -a RETURN
45 local -a RANGES
46 local -a RANGE_EXPANDED
47
48 readarray -t RANGES < <(split_list "$RANGE_LIST" ",")
49
50 for RANGE in "${RANGES[@]}"; do
51 readarray -t RANGE_EXPANDED < <(expand_range "$RANGE")
52 RETURN+=( "${RANGE_EXPANDED[@]}" )
53 unset RANGE_EXPANDED
54 done
55
56 readarray -t RETURN \
57 < <(printf "%s\n" "${RETURN[@]}" |sort -nu)
58
59 printf '%s\n' "${RETURN[@]}"
60 }
61
62 readarray -t RANGE_LIST_EXPANDED \
63 < <(expand_range_list "$RANGE_LIST_INPUT" ",")
64
65 echo "RANGE_LIST_EXPANDED: ${RANGE_LIST_EXPANDED[*]}"