There is lots of books, videos and manuals about bash. So it is hard to tell if one is good or not. By advanced bash I mean regular expressions, complex scripts, and kind-of obscure options of basic commands no beginner tutorial tells about.

you are viewing a single comment's thread
view the rest of the comments
[–] 13 points 3 months ago* (last edited 3 months ago) (1 child)

shellcheck.net

Also, advanced bash is mostly about structuring code for maintainability, exception handling and some good tidbit functions you can easily adapt. Actually a good experience for creating maintianable lower-level code too.

Edit: right, most important: always set a default value, if you have a variable in a path.

That said, i have a (POSIX) cheatsheet i still regularly use. Most important parts:

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## exit codes for GNU/Linux
┌──────────┬────────────────────────────────────────────────────────┬─────────────────────────────────────┐
│ Exitcode │ Meaning                                                │ Example                             │
├──────────┼────────────────────────────────────────────────────────┼─────────────────────────────────────┤
│ 1        │ Catchall for general errors, such as "divide by zero"  │ let "var1 = 1/0"                    │
│ 2        │ Misuse of shell builtins: Missing keyword or command.  │ empty_function() {}                 │
│ 126      │ cannot invoke requested command                        │ /dev/null                           │
│ 127      │ A utility to be executed was not found                 │ evho                                │
│ 128      │ Invalid argument to exit: only integer args in the     │ exit 3.14159                        │
│          │ range 0 - 255 allowed                                  │                                     │
│ 128+n    │ A command was interrupted by signal n (128 + n)        │ kill -9 $PPID returns 137 (128 + 9) │
│ 130      │ Script terminated by Ctrl+C: fatal error signal 2,     │ Ctl-C                               │
│          │ (130 = 128 + 2, see above)                             │                                     │
│ 255*     │ Exit status out of range: exit takes only integer args │ exit -1                             │
│          │ in the range 0 - 255                                   │                                     │
└──────────┴────────────────────────────────────────────────────────┴─────────────────────────────────────┘

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Numeric True/False

OR ||:
1 + 1 = 1         TRUE || TRUE = TRUE
1 + 0 = 1         TRUE || FALSE = TRUE
0 + 0 = 0         FALSE || FALSE = FALSE
AND &&:
1 * 1 = 1         TRUE && TRUE = TRUE
1 * 0 = 0         TRUE && FALSE = FALSE
0 * 0 = 0         FALSE && FALSE = FALSE

Btw; lowercase true/false are special in that they set the respective state, standalone or as argument.
     Said state can be set to variables too, for constructs like: var=true; $var && echo True


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Variable-Expansion

┌───────────────────────┬───────┬───────┬───────────┐
│               VAR is: │ unset │ empty │ non-empty │
├───────────────────────┼───────┼───────┼───────────┤
│ [ -z "${VAR}"       ] │ true  │ true  │ false     │
│ [ -z "${VAR+set}"   ] │ true  │ false │ false     │
│ [ -z "${VAR-unset}" ] │ false │ true  │ false     │
│ [ -n "${VAR}"       ] │ false │ false │ true      │
│ [ -n "${VAR+set}"   ] │ false │ true  │ true      │
│ [ -n "${VAR-unset}" ] │ true  │ false │ true      │
└───────────────────────┴───────┴───────┴───────────┘

Btw,
[ -z $var ] &&
[ -n $var ] ||
are *not* the same; the first ist exact match, rather false, the second forgiving, rather true.

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Parameter expansion

# Use these in place of awk or sed calls when possible
┌─────────────────────────┬─────────────────────────────────────────────┐
│ Parameter               │ Description                                 │
├─────────────────────────┼─────────────────────────────────────────────┤
│ ${VAR/PATTERN/REPLACE}  │ Substitute first pattern with replacement   │
│ ${VAR//PATTERN/REPLACE} │ Substitute all pattern with replacement     │
│ ${VAR#PATTERN}          │ Remove shortest match of pattern from start │
│ ${VAR##PATTERN}         │ Remove longest match of pattern from start  │
│ ${VAR%PATTERN}          │ Remove shortest match of pattern from end   │
│ ${VAR%%PATTERN}         │ Remove longest match of pattern from end    │
│ ${#VAR}                 │ Length of var in characters                 │
└─────────────────────────┴─────────────────────────────────────────────┘

Summary:
* String manipulation with ${VAR#PREFIX}, ${VAR##PREFIX}, ${VAR%SUFFIX} and ${VAR%%SUFFIX}.
* Conditional treatment of unset variables with ${VAR-DEFAULT}, ${VAR=DEFAULT}, ${VAR+FALLBACK}
   and ${VAR?MESSAGE} as well as the unset-or-empty variants with :-, :=, :+ and :?.
* Variable length with ${#VAR}.

filename=/foo/bar.baz
"${filename%/*}"  # /foo      # dirname
"${filename%.*}"  # /foo/bar  # filename
"${filename##*/}" # bar.baz   # basename
"${filename##*.}" # baz       # file-ext

Btw, if it goes over 100 to 150 loc, go Python at least. No matter how disciplined you are or how clean your code is, it gets messy.

  • source
  • hideshow 1 child comment