summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2021-11-26 09:46:43 +0000
committerPaul Buetow <paul@buetow.org>2021-11-26 09:46:43 +0000
commit3960d95e3481787acd4799c995212353e40c7263 (patch)
tree0e75e543618a58ea4213e442cf2656a3bc0a06a4
parent87141cac574b56b8b04df3eb03644c3e02589ca6 (diff)
more on this
-rw-r--r--gemfeed/2021-11-21-bash-golfing.draft.gmi252
1 files changed, 192 insertions, 60 deletions
diff --git a/gemfeed/2021-11-21-bash-golfing.draft.gmi b/gemfeed/2021-11-21-bash-golfing.draft.gmi
index a743bcb7..2293244f 100644
--- a/gemfeed/2021-11-21-bash-golfing.draft.gmi
+++ b/gemfeed/2021-11-21-bash-golfing.draft.gmi
@@ -2,7 +2,7 @@
> Written by Paul Buetow 2021-11-21
-This blog post is about some (mostly uncommon) bash tricks I came across in the past.
+This blog post is about some random Bash tricks I came across in the past. It's a collection of smaller articles I wrote in an older blog of mine plus the translation from German into English plus some updates and additions.
## TCP/IP networking
@@ -233,9 +233,9 @@ The "tar" command understands "-" too. This example tars up some local directory
And this is yet another example of using "-", but this time using the "file" command:
```
-$ head -n 1 test.sh
+$ head -n 1 grandmaster.sh
#!/usr/bin/env bash
-$ file - < <(head -n 1 test.sh)
+$ file - < <(head -n 1 grandmaster.sh)
/dev/stdin: a /usr/bin/env bash script, ASCII text executable
```
@@ -459,7 +459,7 @@ Bratwurst
You can also override the default file descriptors, like demonstrated in this script:
```
-❯ cat test.sh
+❯ cat grandmaster.sh
#!/usr/bin/env bash
# Write a file data-file containing two lines
@@ -488,76 +488,208 @@ exec 0<&6 6<&-
Let's execute it:
```
-❯ ./test.sh
+❯ chmod 750 ./grandmaster.sh
+❯ ./grandmaster.sh
First line: Learn You a Haskell
Second line: for Great Good
```
-## Here
+## HERE
-Wie in vielen anderen Skriptsprachen unterstützt auch die Bash sog. Here-Dokumente. Hier ein kleines
-Beispiel:
-pb@titania: $ cat END
-> Hallo Welt
-> it’s $(date)
+We have touched HERE-documents and HERE-strings already in this post. Let's do some more examples. The following "cat" receives a multi line string from stdin. In this case the input multi line string is a HERE-document. As you can see, it also interpolates variables (in this case the output of "date" running in a sub-shell).
+
+```
+❯ cat <<END
+> Hello World
+> It’s $(date)
+> END
+Hello World
+It's Fri 26 Nov 08:46:52 GMT 2021
+```
+
+You can also write it this way, but that's less readable (it's good for an obfuscation contest):
+
+```
+❯ <<END cat
+> Hello Universe
+> It’s $(date)
> END
-Hallo Welt
-it’s Fr 13. Mai 11:07:36 CEST 2011
-pb@titania: $
-Neben kennt die Bash auch den Operator <. Während
-sog. Here-Strings verwendet.
-für Here-Dokumente reserviert ist, wird < für
-So könnte man ohne einen Here-String prüfen, ob eine Variable einen bestimmte Substring enthält:
-VAR=foo; if echo ” $VAR” | grep -q foo; then echo \ $VAR contains foo; fi
-Und so mit Here-String:
-if grep -q foo < ” $VAR”; then echo \ $VAR contains foo; fi
-Wie unschwer zu erkennen ist spart man sich hier einiges an Tipparbeit (ein echo und eine Pipe weniger).
-(PS: Das könnte man auch ohne grep, nämlich mit Bash Regexp überprüfen, aber dazu evtl. später mehr).
-
-Here-Strings können auch in Kombination mit read angewandt werden:
-
-pb@titania:
-pb@titania:
-pb@titania:
+Hello Universe
+It's Fri 26 Nov 08:47:32 GMT 2021
+```
+
+Besides of an HERE-document there is also a so-called HERE-string. Besides of...
+
+```
+❯ declare VAR=foo
+❯ if echo "$VAR" | grep -q foo; then
+> echo '$VAR ontains foo'
+> fi
+$VAR ontains foo
+```
+
+you can use a HERE-string like that:
+
+```
+❯ if grep -q foo <<< "$VAR"; then
+> echo '$VAR contains foo'
+> fi
+$VAR contains foo
+```
+
+or even shorter:
+
+```
+❯ grep -q foo <<< "$VAR" && echo '$VAR contains foo'
+$VAR contains foo
+```
+
+You could also use a Bash regex to accomplish the same thing, but the point of the examples so far is to demonstrate HERE-{documents,strings}:
+
+```
+❯ if [[ "$VAR" =~ foo ]]; then echo yay; fi
+yay
+```
+
+You can also use it with "read", e.g. read a sentence into an array of words:
+
+```
+❯ read a <<< ja
+❯ echo $a
+ja
+❯ read b <<< 'NEIN!!!'
+❯ echo $b
+NEIN!!!
+❯ dumdidumstring='Learn you a Golang for Great Good'
+❯ read -a words <<< "$dumdidumstring"
+❯ echo ${words[0]}
Learn
-pb@titania:
-you
-pb@titania:
-a
-$ dumdidumstring=”Learn you a Haskell for Great Good”
-$ read -a words < ” $dumdidumstring”
-$ echo $ {words[0] }
-$ echo $ {words[1] }
-$ echo $ {words[2] }
-Das -a bei read bezweckt, dass words aus dem Here-String als Array befüllt werden soll.
-Mittels Here-String kann man auch eine Zeile einer Textdatei prependen:
-pb@titania:/tmp $ echo for Great Good > file.txt
-pb@titania:/tmp $ cat - file.txt <”Learn you a Haskell”
-Learn you a Haskell
-for Great Good
-Das hat allerdings den Nachteil, dass man das Ergebnis zuerst in eine temporäre Datei oder Variable schreiben
-muss, bevor man die Originaldatei file.txt überschreibt. Ansonsten kommt es zu einem Fehler:
-pb@titania:/tmp $ cat - file.txt <”Learn you a Haskell” > file.txt
-cat: file.txt: Eingabedatei ist Ausgabedatei
-Natürlich wäre hierbei sed sowieso das bessere Tool der Wahl:
-
-pb@titania:/tmp $ echo for great Good > file.txt
-pb@titania:/tmp $ sed -i -e ’1i\
-Learn you a Haskell’ file.txt
-pb@titania:/tmp $ cat file.txt
-Learn you a Haskell
-for great Good
-pb@titania:/tmp $
+❯ echo ${words[3]}
+Golang
+```
-## xargs
+The following is good for an obfuscation contest too:
+
+```
+❯ echo 'I like Perl too' > perllove.txt
+❯ cat - perllove.txt <<< "$dumdidumstring"
+Learn you a Golang for Great Good
+I like Perl too
+```
## RANDOM
-## -x and set -x
+Random is a special builtin variable containing a pseudo random number each time it's used.
+
+```
+❯ echo $RANDOM
+11811
+❯ echo $RANDOM
+14997
+❯ echo $RANDOM
+9104
+❯ echo $RANDOM
+26750
+```
+
+That's very useful if you want to randomly delay the execution of your scripts when you run it on many servers concurrently just to spread the server load better.
+
+Let's say you want to introduce a random delay of 1 minute you can do:
+
+```
+❯ cat ./calc_answer_to_ultimate_question_in_life.sh
+#!/usr/bin/env bash
+
+declare -i MAX_DELAY=60
+
+random_delay () {
+ declare -i sleep_for=$((RANDOM % MAX_DELAY))
+ echo "Delaying script execution for $sleep_for seconds..."
+ sleep $sleep_for
+ echo 'Continuing script execution...'
+}
+
+main () {
+ random_delay
+ # From here, do the real work.
+}
+
+main
+
+❯ ./calc_answer_to_ultimate_question_in_life.sh
+Delaying script execution for 42 seconds...
+Continuing script execution...
+```
+
+## set -x and set -e and pipefile
+
+In my opinion, -x and -e and pipefile are the most useful Bash options. Let's have a look at them one after another.
+
+### -x
+
+-x prints commands and their arguments as they are executed. This helps developing and debugging your Bash code:
+
+```
+❯ set -x
+❯ square () { local -i num=$1; echo $((num*num)); }
+❯ num=11; echo "Square of $num is $(square $num)"
++ num=11
+++ square 11
+++ local -i num=11
+++ echo 121
++ echo 'Square of 11 is 121'
+Square of 11 is 121
+```
+
+However, you need to set -x also for the sub-shell in oder to print out what is happening:
+
+```
+❯ num=12; echo "Square of $num is $(set -x;square $num)"
++ num=12
+++ set -x
+++ square 12
+++ local -i num=12
+++ echo 144
++ echo 'Square of 12 is 144'
+Square of 12 is 144
+❯
+```
+
+You can also use the option like this, if helped me personally a lot:
+
+```
+❯ bash -x ./half_broken_script_to_be_debugged.sh
+```
+
+Let's do that on one of the example scripts we used earlier:
+
+```
+❯ bash -x ./grandmaster.sh
++ bash -x ./grandmaster.sh
++ echo Learn You a Haskell
++ echo for Great Good
++ exec
++ exec
++ declare LINE1 LINE2
++ read LINE1
++ read LINE2
++ echo First line: Learn You a Haskell
+First line: Learn You a Haskell
++ echo Second line: for Great Good
+Second line: for Great Good
++ exec
+❯
+```
+
+## xargs
## More
-Reference to my bash coding style guide.
+Have also a look at my personal Bash coding style guide:
+
+=> ./2021-05-16-personal-bash-coding-style-guide.gmi Personal Bash coding style guide
+
+TODO: Also link from my Bash coding style guide to this article.
E-Mail me your thoughts at comments@mx.buetow.org!