Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
becki:linux:bash [2011-11-08 10:50] becki |
becki:linux:bash [2016-03-03 11:25] (aktuell) becki [File Inclusion, Command Execution] |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== Bash Programming ====== | + | ====== Bash Programming == |
+ | ===== Documentation == | ||
+ | - [[kman>man1/bash.1|Bash man page]] | ||
+ | - [[http://tldp.org/LDP/abs/html/|Advanced Bash-Scripting Guide]] | ||
===== File Inclusion, Command Execution == | ===== File Inclusion, Command Execution == | ||
Zeile 13: | Zeile 16: | ||
**command** | **command** | ||
- | when the shell encounters a command, it forks off a child process to actually execute the command (external commands only; from abs-guide) FIXME: Is this true? Isn't this ''%%command &%%''? | + | when the shell encounters a command, it forks off a child process to actually execute the command (external commands only; from abs-guide). Parent script blocks until child process ends |
+ | |||
+ | **command &** | ||
+ | |||
+ | forks off a child process to execute the command and put child process into background so that the parent script continues immediately | ||
**eval command ...** | **eval command ...** | ||
Zeile 20: | Zeile 27: | ||
For me useful if command contains spaces witch are protected by single quotes, eg ''%%wget -S --header'Content-Type: application/json'%%''. Without eval, ''%%--header'Content-Type:%%'' and ''%%application/json'%%'' would be interpreted as 2 single arguments | For me useful if command contains spaces witch are protected by single quotes, eg ''%%wget -S --header'Content-Type: application/json'%%''. Without eval, ''%%--header'Content-Type:%%'' and ''%%application/json'%%'' would be interpreted as 2 single arguments | ||
+ | |||
+ | ===== Subshells == | ||
+ | |||
+ | FIXME | ||
+ | |||
+ | ===== Coprocesses == | ||
+ | |||
+ | The following example starts a shell function as a coproc and uses the coproc to manipulate a string: | ||
+ | |||
+ | <code bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | test_coproc() { | ||
+ | read rein | ||
+ | echo ">$rein<" | ||
+ | } | ||
+ | |||
+ | coproc test_coproc | ||
+ | |||
+ | echo "Hallo" >&${COPROC[1]} | ||
+ | read -u ${COPROC[0]} rein | ||
+ | echo "$rein" | ||
+ | #cat <&${COPROC[0]} # alternative | ||
+ | </code> | ||
+ | |||
+ | ===== Expansion == | ||
+ | |||
+ | FIXME doc ''*'' and ''?'' | ||
+ | |||
+ | <code bash> | ||
+ | echo {a,}quota.{group,user}.new | ||
+ | # prints: aquota.group.new aquota.user.new quota.group.new quota.user.new | ||
+ | # without any regard to the content of the working directory | ||
+ | </code> | ||
+ | |||
+ | ===== Variables == | ||
+ | |||
+ | |||
+ | $meli is a shortcut for ${meli} | ||
+ | |||
+ | ==== Variable Variables == | ||
+ | |||
+ | <code bash> | ||
+ | # get a value from a variable (meli) over a 'pointer' (who): (from abs-guide) | ||
+ | meli=Melanie | ||
+ | who=meli # who is used as pointer to meli | ||
+ | adr=${!who} # now $adr contains Melanie | ||
+ | |||
+ | # set a value into a variable (meli) over a 'pointer' (who): (tried myself) | ||
+ | meli="" | ||
+ | who=meli | ||
+ | eval $(echo $who)=Melanie # now $meli contains Melanie | ||
+ | </code> | ||
+ | |||
+ | ==== Special Variables == | ||
+ | |||
+ | <code bash> | ||
+ | $# # number of command line arguments | ||
+ | $* # Arguments as one word | ||
+ | $@ # Arguments as separate words | ||
+ | $$ # Pid of script | ||
+ | $? # return value of command (& function?) | ||
+ | $! # PID of last job run in background | ||
+ | $0 # full name of script | ||
+ | $1 # first argument of script | ||
+ | </code> | ||
+ | |||
+ | Following a ''shift'' , the ''$@'' holds the remaining command-line parameters, lacking the previous ''$1'', which was lost(([[tldp>LDP/abs/html/othertypesv.html#EX19|Using shift]])). | ||
+ | |||
+ | ==== Default Values == | ||
+ | |||
+ | If variable is not set, expand to default value: | ||
+ | |||
+ | <code bash> | ||
+ | ${variable:-defaultvalue} | ||
+ | |||
+ | # Example: | ||
+ | #Keep Value of VERSION or if not set yet, set it to 3.9: | ||
+ | VERSION=${VERSION:-3.9} | ||
+ | </code> | ||
+ | |||
+ | [[tldp>LDP/abs/html/parameter-substitution.html|Source]] | ||
===== Arrays == | ===== Arrays == | ||
Zeile 32: | Zeile 121: | ||
echo ${app[appix]} # XINE | echo ${app[appix]} # XINE | ||
</code> | </code> | ||
+ | |||
+ | ===== Maps == | ||
+ | |||
+ | See http://stackoverflow.com/questions/1494178/how-to-define-hash-tables-in-bash | ||
===== Loops == | ===== Loops == | ||
Zeile 49: | Zeile 142: | ||
for arg in "$@"; do # $@ sees arguments as separate words. | for arg in "$@"; do # $@ sees arguments as separate words. | ||
echo $arg | echo $arg | ||
+ | done | ||
+ | |||
+ | # Loop through all ogg files of current dir. This is whitepace-save | ||
+ | for fn in *.ogg; do | ||
+ | echo $fn | ||
done | done | ||
Zeile 69: | Zeile 167: | ||
done | done | ||
</code> | </code> | ||
- | |||
- | ===== Variables == | ||
- | |||
- | $meli is a shortcut for ${meli} | ||
- | |||
- | ==== Variable Variables == | ||
- | |||
- | <code bash> | ||
- | # get a value from a variable (meli) over a 'pointer' (who): (from abs-guide) | ||
- | meli=Melanie | ||
- | who=meli # who is used as pointer to meli | ||
- | adr=${!who} # now $adr contains Melanie | ||
- | |||
- | # set a value into a variable (meli) over a 'pointer' (who): (tried myself) | ||
- | meli="" | ||
- | who=meli | ||
- | eval $(echo $who)=Melanie # now $meli contains Melanie | ||
- | </code> | ||
- | |||
- | ==== Special Variables == | ||
- | |||
- | <code bash> | ||
- | $# # number of command line arguments | ||
- | $* # Arguments as one word | ||
- | $@ # Arguments as separate words | ||
- | $$ # Pid of script | ||
- | $? # return value of command (& function?) | ||
- | $! # PID of last job run in background | ||
- | $0 # full name of script | ||
- | $1 # first argument of script | ||
- | </code> | ||
- | |||
- | Following a ''shift'' , the ''$@'' holds the remaining command-line parameters, lacking the previous ''$1'', which was lost(([[tldp>LDP/abs/html/othertypesv.html#EX19|Using shift]])). | ||
===== Quoting == | ===== Quoting == | ||
Zeile 122: | Zeile 187: | ||
===== Functions == | ===== Functions == | ||
+ | ==== Parameters == | ||
+ | FIXME | ||
<code bash> | <code bash> | ||
- | query() { | + | myfunc() { |
- | echo $*; echo $@; echo $1 | + | echo $* #-> eins zwei drei |
+ | echo $@ #-> eins zwei drei | ||
+ | echo $1 #-> eins | ||
} | } | ||
- | query # call the function | + | myfunc eins zwei drei # call the function |
+ | </code> | ||
+ | |||
+ | ==== Exit Status and return Value == | ||
+ | |||
+ | The exit status may be explicitly specified by a return statement, otherwise it is the exit status of the last command in the function. Exit status can be checked with ''$?''. | ||
+ | |||
+ | Here is a method to return a string along with the exit status: | ||
+ | |||
+ | <code bash> | ||
+ | myfunc() { | ||
+ | echo "Hello $1" | ||
+ | } | ||
+ | |||
+ | res=$(myfunc 'crazy world') # Oddly no quotes necessary in bash and ash | ||
+ | echo ">>$res<<" | ||
+ | </code> | ||
+ | |||
+ | By using a separator (tab) and the cut command it is possible to return more than one value: | ||
+ | |||
+ | <code bash> | ||
+ | myfunc() { | ||
+ | echo -e "EINS\tZWEI" | ||
+ | } | ||
+ | |||
+ | buf=$(myfunc) | ||
+ | eins=$(echo "$buf" | cut -f1) | ||
+ | zwei=$(echo "$buf" | cut -f2) | ||
+ | |||
+ | echo "$eins - $zwei" #-> EINS - ZWEI | ||
</code> | </code> | ||
Zeile 163: | Zeile 261: | ||
-s file True if file exists and has a size greater than zero | -s file True if file exists and has a size greater than zero | ||
-x file has execute permission (for the user running the test) | -x file has execute permission (for the user running the test) | ||
+ | -z string is null, that is, has zero length | ||
+ | -n string is not null, that is, has not zero length | ||
+ | |||
# Example: | # Example: | ||
if [ ! -r "$sourcefile" ]; then | if [ ! -r "$sourcefile" ]; then | ||
Zeile 189: | Zeile 290: | ||
<code bash> | <code bash> | ||
abort () { | abort () { | ||
- | if [ "$1" ]; then echo "$(basename $0): $1" >&2; fi | + | if [ -n "$1" ]; then echo "$(basename $0): $1" >&2; fi |
- | if [ "$2" ]; then err="$2"; else err=1; fi | + | if [ -n "$2" ]; then err="$2"; else err=1; fi |
exit $err | exit $err | ||
} | } |