NOTES INDEX This page is part of the collection of "notes" - these can be considered to be micro-blogs.
Bash Environment Variable Functions

Bash Environment Variable Functions

A set of useful (Linux) Bash environment variable functions, taken / adapted, and added some information (not a plain copy) from blog post: https://hackaday.com/2022/01/26/linux-fu-bash-strings/

The examples below start with a $ if it is the command line, and without if it is the output (or input) of the command.

Shell script command line arguments

$ # Create a script /tmp/script.sh - end cat by hitting ctrl-d (or use a text editor instead of cat)
$ cat >/tmp/script.sh
#!/bin/bash

echo "script name: $0"
echo "nr of arguments $#"
echo "param 1: $1"
echo "all params: $*"
# remove first param
shift
echo "nr of arguments $#"
echo "param 1: $1"
echo "all params: $*"
<ctrl-d>

$ # make executable
$ chmod 755 /tmp/script.sh
$ # execute
$ /tmp/script.sh hello hi test
script name: /tmp/script.sh
nr of arguments 3
param 1: hello
all params: hello hi test
nr of arguments 2
param 1: hi
all params: hi test

$ # Run with quoted argument
$ /tmp/script.sh "hello hi" test
script name: /tmp/script.sh
nr of arguments 2
param 1: hello hi
all params: hello hi test
nr of arguments 1
param 1: test
all params: test

Numeric

$ # Length
$ X="Some test value ABC 123!"
$ echo "${#X}"
24

$ # Calculations
$ X=120
$ echo "$(( $X + 3 ))"
123

$ # Numeric comparison in if, using numeric context (( ))
$ if (( $X > 2 )); then echo "over 2"; fi
over 2

$ # Numeric comparison using "/bin/["
$ if [ $X -gt 2 ]; then echo "over 2"; fi
over 2

$ # Numeric comparison using bash buill-in "[["
$ if [[ $X -gt 2 ]]; then echo yes; fi
yes

Substrings

$ # Substrings ${VAR:start:length}
$ # Where start is zero based start pos when positive
$ # Where start is -1 based start position from the end backwards if negative (needs leading space!)
$ # Where end is number of characters when positive
$ # Where end is position from end when negative (no leading space needed)

$ # show substring starting at 11th char for 5 long
$ X="Some test value ABC 123!"
$ echo "${X:10:5}"
value

$ # Show last char
$ X="Some test value ABC 123!"
$ echo "${X: -1}"
!

$ # Show from 11th char up to end minus one char
$ X="Some test value ABC 123!"
$ echo "${X:10:-1}"
value ABC 123

$ # warning: if string value is too short, this could lead to errors.
$ # oddly enough only if the start offset is within the string.
$ X="hello"
$ echo "${X:1:-5}"
bash: -5: substring expression < 0
$ echo "${X:10:-5}"

$ X="hello-test"
$ echo "${X:1:-5}"
ello

Remove leading or trailing parts

$ # removing leading or trailing parts using a wildcard * pattern (not regex)

$ # find last e and delete from there
$ X="Some test value ABC 123!"
$ echo "${X%e*}"
Some test valu

$ # more serious example, remove filename extension (remove last .txt*, also matches .txt2)
$ X="file.txt.name.txt"
$ echo "${X%.txt*}"
file.txt.name
$ X="file.txt.name.txt2"
$ echo "${X%.txt*}"
file.txt.name

$ # more serious example, remove filename extension (remove last .txt if there, so .txt2 not matched)
$ X="file.txt.name.txt"
$ echo "${X%.txt}"
file.txt.name
$ X="file.txt.name.txt2"
$ echo "${X%.txt}"
file.txt.name.txt2

$ # find first e and delete from there
$ X="Some test value ABC 123!"
$ echo "${X%%e*}"
Som

$ # find first e and delete up to and including there
$ X="Some test value ABC 123!"
$ echo "${X#*e}"
 test value ABC 123!

$ # find last e and delete up to and including there
$ X="Some test value ABC 123!"
$ echo "${X##*e}"
 ABC 123!

Search / Replace

$ # Search/Replace, single / is replace once, // is replace all.
$ # And you can use #*xxx or %xxx* to match to start or end.

$ # single replace
$ X="Some test value ABC ABC 123!"
$ echo "${X/ABC/def}"
Some test value def ABC 123!

$ # replace all
$ X="Some test value ABC ABC 123!"
$ echo "${X//AB/de}"
Some test value deC deC 123!

$ # Replace all up to and including test
$ X="Some test value ABC ABC 123!"
$ echo "${X/#*test/blah}"
blah value ABC ABC 123!

$ # Replace from test to end
$ X="Some test value ABC ABC 123!"
$ echo "${X/%test*/blah}"
Some blah

$ # Note: my bash does not seem to mind leaving the # or % off in above examples.
$ # Other interesting use? if word exists replace full string:
$ X="Some test value ABC ABC 123!"
$ echo "${X/*test*/blah}"
blah
$ echo "${X/*text*/blah}"
Some test value ABC ABC 123!

$ # Replace file name extension
$ X="file.txt.name.txt"
$ echo "${X/%.txt/.conv}"
file.txt.name.conv
$ X="file.txt.name.txt2"
$ echo "${X/%.txt/.conv}"
file.txt.name.txt2

Default values

$ # Default value
$ X=
$ echo "${X:-Hello} / ${X}"
Hello / 
$ X=Hi
$ echo "${X:-Hello} / ${X}"
Hi / Hi

$ # Default assigned to the var
$ X=
$ echo "${X:=Hello} / ${X}"
Hello / Hello
$ X=Hi
$ echo "${X:=Hello} / ${X}"
Hi / Hi

$ # Show some value if variable has been set (not updating its value)
$ X=
$ echo "${X:+Hello} / ${X}"
 / 
$ X=Hi
$ echo "${X:+Hello} / ${X}"
Hello / Hi

Changing case

$ # Changing case

$ # Only change first char
$ X="some test value ABC 123!"
$ echo "${X^}"
Some test value ABC 123!

$ # All UPPERCASE
$ X="some test value ABC 123!"
$ echo "${X^^}"
SOME TEST VALUE ABC 123!

$ # Change all e's to E
$ X="some test value ABC 123!"
$ echo "${X^^e}"
somE tEst valuE ABC 123!
$ echo "${X^^[e]}"
somE tEst valuE ABC 123!

$ # Change all e's and a's to E and A
$ X="some test value ABC 123!"
$ echo "${X^^[ea]}"
somE tEst vAluE ABC 123!

$ # Change all e up to s to UPPER
$ X="some test value ABC 123!"
$ echo "${X^^[e-s]}"
SOME tESt vaLuE ABC 123!

$ # Change first char to lower
$ X="SOme tESt value ABC 123!"
$ echo "${X,}"
sOme tESt value ABC 123!

$ # Change all to lower
$ X="SOme tESt value ABC 123!"
$ echo "${X,,}"
some test value abc 123!

$ # Change B to lower
$ X="SOme tESt value ABC 123!"
$ echo "${X,,B}"
SOme tESt value AbC 123!
$ echo "${X,,[B]}"
SOme tESt value AbC 123!

$ # Newer versions of bash can use ${VAR@U} and ${VAR@L} ${VAR@u} and ${VAR@l} for all/one to upper/lower
$ # Does not work on my version [GNU bash, version 5.0.17(1)-release], so untested.

Bash built-in if tests

$ # Bash built in if tests, no need to quote the var
$ X="yes yes"
$ if [[ $X == "yes yes" ]]; then echo "y"; fi
y
$ # the /bin/[ errors out on this
$ if [ $X == "yes yes" ]; then echo "y"; fi
bash: [: too many arguments

$ # Bash built in if tests, supports REGEX matching
$ X="Some test value ABC 123!"
$ if [[ $X =~ test ]] ; then echo "y"; fi
y
$ if [[ $X =~ tst ]] ; then echo "y"; fi
$ if [[ $X =~ [a]BC ]] ; then echo "y"; fi
$ if [[ $X =~ [aA]BC ]] ; then echo "y"; fi
y
$ if [[ $X =~ [tT]est ]] ; then echo "y"; fi
y
$ if [[ $X =~ [TX]est ]] ; then echo "y"; fi
$ if [[ $X =~ t.st ]] ; then echo "y"; fi
y
$ if [[ $X =~ tes.* ]] ; then echo "y"; fi
y

$ # Numeric
$ if [[ 1 > 2 ]] ; then echo "y"; fi
$ if [[ 3 > 2 ]] ; then echo "y"; fi
y
$ # Although you should probably use this
$ if (( 1 > 2 )) ; then echo "y"; fi
$ if (( 3 > 2 )) ; then echo "y"; fi
y
$ # expr - can do integer calculations and some functions, type expr --help for more info

$ # Length example:
$ X="Some test value ABC 123!"
$ expr length "${X}"
24

$ # Calculations
$ X=120
$ echo $(expr $X + 3 )
123

$ # Need non integer calculations? expr wont work, but you can use bc
$ # Type "man bc" or "bc --help" for more information

$ expr 1.5 + 2
expr: non-integer argument

$ echo "1.5 + 2" | bc
3.5

$ echo "Or inline: $(echo "1.5 + 2" | bc) is also possible"
Or inline: 3.5 is also possible

January 28, 2022

Leave a Reply

Your email address will not be published.