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.

  • MonkderVierte@lemmy.zip
    link
    fedilink
    arrow-up
    9
    ·
    edit-2
    13 hours ago

    shellcheck.net

    Also, adcanced 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.

    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}"       ] │ truetruefalse     │
    │ [ -z "${VAR+set}"   ] │ truefalsefalse     │
    │ [ -z "${VAR-unset}" ] │ falsetruefalse     │
    │ [ -n "${VAR}"       ] │ falsefalsetrue      │
    │ [ -n "${VAR+set}"   ] │ falsetruetrue      │
    │ [ -n "${VAR-unset}" ] │ truefalsetrue      │
    └───────────────────────┴───────┴───────┴───────────┘
    
    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.