From 21a13652df728c9571f899caf4949d5d46f49db7 Mon Sep 17 00:00:00 2001 From: johannst Date: Wed, 1 May 2024 17:39:45 +0000 Subject: deploy: 7ca41565c4e70b212cb88a4d18c18fa35768df6d --- shells/bash.html | 457 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 457 insertions(+) create mode 100644 shells/bash.html (limited to 'shells/bash.html') diff --git a/shells/bash.html b/shells/bash.html new file mode 100644 index 0000000..fe98ee4 --- /dev/null +++ b/shells/bash.html @@ -0,0 +1,457 @@ + + + + + + bash - Notes + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+

bash(1)

+

Expansion

+

Generator

+
# generate sequence from n to m
+{n..m}
+# generate sequence from n to m step by s
+{n..m..s}
+
+# expand cartesian product
+{a,b}{c,d}
+
+

Parameter

+
# default value
+bar=${foo:-some_val}  # if $foo set, then bar=$foo else bar=some_val
+
+# alternate value
+bar=${foo:+bla $foo}  # if $foo set, then bar="bla $foo" else bar=""
+
+# check param set
+bar=${foo:?msg}  # if $foo set, then bar=$foo else exit and print msg
+
+# indirect
+FOO=foo
+BAR=FOO
+bar=${!BAR}  # deref value of BAR -> bar=$FOO
+
+# prefix
+${foo#prefix}  # remove prefix when expanding $foo
+# suffix
+${foo%suffix}  # remove suffix when expanding $foo
+
+# substitute
+${foo/pattern/string}  # replace pattern with string when expanding foo
+# pattern starts with
+# '/'   replace all occurences of pattern
+# '#'   pattern match at beginning
+# '%'   pattern match at end
+
+# set programmatically with priintf builtin
+printf -v "VAR1" "abc"
+NAME=VAR2
+printf -v "$NAME" "%s" "def"
+
+
+

Note: prefix/suffix/pattern are expanded as pathnames.

+
+

Pathname

+
*           match any string
+?           match any single char
+\\          match backslash
+[abc]       match any char of 'a' 'b' 'c'
+[a-z]       match any char between 'a' - 'z'
+[^ab]       negate, match all not 'a' 'b'
+[:class:]   match any char in class, available:
+              alnum,alpha,ascii,blank,cntrl,digit,graph,lower,
+              print,punct,space,upper,word,xdigit
+
+

With extglob shell option enabled it is possible to have more powerful +patterns. In the following pattern-list is one ore more patterns separated +by | char.

+
?(pattern-list)   matches zero or one occurrence of the given patterns
+*(pattern-list)   matches zero or more occurrences of the given patterns
++(pattern-list)   matches one or more occurrences of the given patterns
+@(pattern-list)   matches one of the given patterns
+!(pattern-list)   matches anything except one of the given patterns
+
+
+

Note: shopt -s extglob/shopt -u extglob to enable/disable extglob +option.

+
+

I/O redirection

+
+

Note: The trick with bash I/O redirection is to interpret from left-to-right.

+
+
# stdout & stderr to file
+command >file 2>&1
+# equivalent
+command &>file
+
+# stderr to stdout & stdout to file
+command 2>&1 >file
+
+
+

The article Bash One-Liners Explained, Part III: All about +redirections +contains some nice visualization to explain bash redirections.

+
+

Explanation

+
j>&i
+
+

Duplicate fd i to fd j, making j a copy of i. See dup2(2).

+

Example:

+
command 2>&1 >file
+
+
    +
  1. duplicate fd 1 to fd 2, effectively redirecting stderr to stdout
  2. +
  3. redirect stdout to file
  4. +
+

Process substitution (ref)

+

Process substitution allows to redirect the stdout of multiple processes at +once.

+
vim -d <(grep foo bar) <(grep foo moose)
+
+

Command grouping

+

Execute commands in a group with or without subshell. Can be used to easily +redirect stdout/stderr of all commands in the group into one file.

+
# Group commands without subshell.
+v=abc ; { v=foo; echo $v; } ; echo $v
+# foo
+# foo
+
+# Group commands with subshell.
+v=abc ; ( v=foo; echo $v; ) ; echo $v
+# foo
+# abc
+
+

Argument parsing with getopts

+

The getopts builtin uses following global variables:

+
    +
  • OPTARG, value of last option argument
  • +
  • OPTIND, index of the next argument to process (user must reset)
  • +
  • OPTERR, display errors if set to 1
  • +
+
getopts <optstring> <param> [<args>]
+
+
    +
  • <optstring> specifies the names of supported options, eg f:c +
      +
    • f: means -f option with an argument
    • +
    • c means -c option without an argument
    • +
    +
  • +
  • <param> specifies a variable name which getopts fills with the last parsed option argument
  • +
  • <args> optionally specify argument string to parse, by default getopts parses $@
  • +
+

Example

+
#!/bin/bash
+function parse_args() {
+    while getopts "f:c" PARAM; do
+        case $PARAM in
+            f) echo "GOT -f $OPTARG";;
+            c) echo "GOT -c";;
+            *) echo "ERR: print usage"; exit 1;;
+        esac
+    done
+    # users responsibility to reset OPTIND
+    OPTIND=1
+}
+
+parse_args -f xxx -c
+parse_args -f yyy
+
+

Regular Expressions

+

Bash supports regular expression matching with the binary operator =~. +The match results can be accessed via the $BASH_REMATCH variable:

+
    +
  • ${BASH_REMATCH[0]} contains the full match
  • +
  • ${BASH_REMATCH[1]} contains match of the first capture group
  • +
+
INPUT='title foo : 1234'
+REGEX='^title (.+) : ([0-9]+)$'
+if [[ $INPUT =~ $REGEX ]]; then
+    echo "${BASH_REMATCH[0]}"    # title foo : 1234
+    echo "${BASH_REMATCH[1]}"    # foo
+    echo "${BASH_REMATCH[2]}"    # 1234
+fi
+
+
+

Caution: When specifying a regex in the [[ ]] block directly, quotes will be treated as part of the pattern. +[[ $INPUT =~ "foo" ]] will match against "foo" not foo!

+
+

Completion

+

The complete builtin is used to interact with the completion system.

+
complete                    # print currently installed completion handler
+complete -F <func> <cmd>    # install <func> as completion handler for <cmd>
+complete -r <cmd>           # uninstall completion handler for <cmd>
+
+

Variables available in completion functions:

+
# in
+$1              # <cmd>
+$2              # current word
+$3              # privous word
+
+COMP_WORDS      # array with current command line words
+COMP_CWORD      # index into COMP_WORDS with current cursor position
+
+# out
+COMPREPLY       # array with possible completions
+
+

The compgen builtin is used to generate possible matches by comparing word +against words generated by option.

+
compgen <option> <word>
+
+# usefule options:
+# -W <list>    specify list of possible completions
+# -d           generate list with dirs
+# -f           generate list with files
+# -u           generate list with users
+# -e           generate list with exported variables
+
+# compare "f" against words "foo" "foobar" "bar" and generate matches
+compgen -W "foo foobar bar" "f"
+
+# compare "hom" against file/dir names and generate matches
+compgen -d -f "hom"
+
+

Example

+

Skeleton to copy/paste for writing simple completions.

+

Assume a program foo with the following interface:

+
foo -c green|red|blue -s low|high -f <file> -h
+
+

The completion handler could be implemented as follows:

+
function _foo() {
+    local curr=$2
+    local prev=$3
+
+    local opts="-c -s -f -h"
+    case $prev in
+        -c) COMPREPLY=( $(compgen -W "green red blue" -- $curr) );;
+        -s) COMPREPLY=( $(compgen -W "low high" -- $curr) );;
+        -f) COMPREPLY=( $(compgen -f -- $curr) );;
+        *)  COMPREPLY=( $(compgen -W "$opts" -- $curr) );;
+    esac
+}
+
+complete -F _foo foo
+
+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + +
+ + -- cgit v1.2.3