Bash Snippets
Hier werden nützliche Befehle und Code Snippets gesammelt.
Flags und Argumente in Bash Skripten
Ein Snippet um Flags wie -h oder --help und Argumente abzufragen. Alle Argumente mit einem Dash werden verarbeitet und aus dem Argumenten entfernt. Übrig bleiben alle anderen Argumente, wie z.B. Dateinamen, in der richtigen Reihenfolge.
# handle dashed arguments and remove them from $@
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
exit 0;;
-o|--output)
if [ -z "$2" ]; then
echo "Error: no output filename given" >&2 ; exit 2
fi
output_file="$2"
shift;shift;; # shift once for the name and once for the value
-*)
echo "Unknown option $1"; exit 1;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift ;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional arguments
Parameter Expansion
Die verschiedenen Möglichkeiten Variablen einzusetzen, zu verändern oder zu ersetzen. Mehr Infos im Bash Manual.
${parameter:−word} # return parameter or word if parameter is null
${parameter:=word} # set parameter to word of parameter is null (does not work with $1)
${parameter:?word} # write word to stderr if parameter is null (exits if noninteractive)
${parameter:offset:length} # return substring
${parameter#word} # remove shortest match from beginning (remove prefix)
${parameter##word} # remove longest match from beginning (remove all slashes)
${parameter%word} # remove shortest match from end (remove file extension)
${parameter%%word} # remove longest match from end (remove everything after first occurrence)
${parameter/pattern/string} # replace first pattern with string
${parameter//pattern/string} # replace all patterns with string
${parameter/#pattern/string} # replace pattern at beginning
${parameter/%pattern/string} # replace pattern at end
${parameter/pattern} # remove pattern
Timer ohne Drift
Ein einfacher Timer mit einem sleep 60 der jede Minute eine Funktion ausführen soll würde mit der
Zeit abdriften, da die Anweisungen zwischen den sleep und auch der Prozessaufruf von sleep
selbst auch Zeit benötigen.
Für ein Timer ohne Drift muss von der Systemzeit ausgegangen werden. Die Bash Variable
EPOCHSECONDS
enthält die Sekunden seit dem 1.1.1970. Mit 60 - ($EPOCHREALTIME % 60) können die Sekunden bis zum
nächsten Aufruf berechnet werden. Zusammen mit
EPOCHREALTIME
, die die Epoch Zeit in Mikrosekunden angibt, kann so die genaue Zeit für einen sleep-Aufruf bestimmt
werden.
timer_seconds=60
timer_micsecs=${timer_seconds}000000
# calculate start time
now_seconds=$(( ${EPOCHSECONDS} % $timer_seconds )) # in seconds
wait_seconds=$(( $timer_seconds - $now_seconds )) # in seconds
begin=$(( ${EPOCHSECONDS} + $wait_seconds ))000000 # in µs
echo "starting timer at $(date -d @${begin%000000})" >&2
count=0
while true; do
next=$((begin+count*$timer_micsecs)) # in µs
now=${EPOCHREALTIME/[.,]} # in µs
diff=$((next-now)) # in µs
diff_real=$(echo "$diff / 1000000" | bc -l) # in s
if test $diff -ge 0; then
sleep $diff_real
fi
if [[ $diff -lt -$timer_micsecs ]]; then
# we missed at least two events - execute immediately, but only once
# calculate new count to skip other events
(( count = (now-begin) / timer_micsecs ))
fi
$@ # execute supplied command with all arguments
(( count++ ))
done