We talked about functions previously, so we have an idea what they are and why we would use them. But in my experience, knowing about something is not the same as seeing how it is used, then using it.
So I've found or invented a few bash functions that show how easy it is to make something useful. Some bash operations are a bit complex, and you have to keep looking up how to do that job. These functions should ease that. After all, that's a large part of what programming is, right?
Another note about these functions: there will be piping and some new commands (awk, sed, grep, wc).
Most of these have to do with string manipulation simply because that is what I deal with a lot, and I'm making an assumption you have a similar experience.
Create a library of bash functions:
Here is what's coming up:
Many of these functions are coded to use a string passed to them as a positional parameter ($1, $2, etc.), with the result returned.
But the result can be saved as a variable if needed.
ltrim() {
echo "${1#"${1%%[![:space:]]*}"}"
}
Note the use of [:space:] in there. That is a special character class of regular expressions. It represents spaces and tabs in text.
The bang (!) ahead of that means to ignore or negate whatever follows.
Usage:myText=" There are 5 leading spaces in this string"
ltrim "$myText"
There are 5 leading spaces in this string
Because of the way HTML and ∴ web pages handle spaces, you may experience some odd effects with this one.
In HTML, browsers typically throw multiple contiguous spaces away - to actually display them you have to use the code (non-breaking space).
If you are scripting for Terminal use, or dealing with a straight ASCII output, you should not have any problems.
Obviously if you have an ltrim, you have to have an rtrim,right?
rtrim() {
echo "${1%"${1##*[![:space:]]}"}"
}
Again using [:space:] to represent spaces or tags.
Usage:
MyText="The slow lazy dog slept until noon! "
echo "-->$MyText<--"
echo "Length: ${#MyText}"
MyTextR=$(rtrim "$MyText")
echo "Trimmed: ${#MyTextR}"
OK, I lied. DON'T throw this one out. It's actually quite old (I remember it from the 1980's).
rot13 is a way of making sensible text appear non-sensible (encipher). This is NOT encryption, but was used for years so a message or some text is not immediately readable (obfuscate).
It works by replacing each letter with the letter 13 places away in the alphabet.
The rot stands for rotation and 13 means how many places away the replacement letter is.
In it's day it was so popular there were applications that would encode or decode text encoded this way. Everyone used it.
More about rot13 here.
This is a simple function using the tr command in a pipe.
rot13() {
echo "$1" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
}
So to see how it works ...
myText="The slow lazy dog slept until noon." rot13 "$myText" Gur fybj ynml qbt fyrcg hagvy abba.
Say what?
Of course to read what it actually says, you have to do the same operation on that string:
myText="Gur fybj ynml qbt fyrcg hagvy abba." rot13 "$myText" The slow lazy dog slept until noon.
Reversing text in a string may mean reversing characters, or words. This one does characters.
reverse() {
local str="$1"
local reversed=""
local len=${#str}
for ((i=$len-1; i>=0; i--))
do
reversed="$reversed${str:$i:1}"
done
echo "$reversed"
}
Usage:
To reverse words in a string, see Strings.
I use this feature sometimes when I want to print the same character or string several times, like this:
rep() {
local str="$1"
local count="$2"
for ((i=1; i<=$count; i++))
do
echo -n "$str" # do not print a newline character
done
}
rep "=" "25"
echo -n " All Done "
rep "=" "25"
Defining the variables str and count as local means they are only accessible in this function. So other variables named the same will not be affected.
Another frequent task you might be getting tired of doing - replace some text with some text.
You have a document with "978-1-003-00641-1" in it several times, but you notice it should be "978-1-003-00641-7". Yes your text editor can do this for you, but we're doing bash here, so ...
swap "isbn.txt" "978-1-003-00641-1" "978-1-003-00641-7" "isbn-fix.txt"
In this one we use sed (stream editor) to do the magic...
swap() {
local input="$1"
local original="$2"
local replaced="$3"
local output="$4"
cat "$input" | sed "s/$original/$replaced/g" > "$output"
cat $4
}
Using local again to define our variables to only affect the function.
Then use cat to read the whole file and pipe it to sed.
sed is pretty cool and we will talk more about it. For now we use the s option to do substitution.
We put the 2 strings we want to swap bookended by the front-slashes /.
Then we add a flag g to indicate we want to swap ALL the occurrences (globally) in the input string.
Finally we give a name to the file we want the fixed output to be put into.
sed is a stream-oriented non-interactive editor. It is designed in a typical Unix fashion, taking input from one command and either sending it to the standard output or piping it to another command.
See sed for the man page.
You would be wise to get to know this one well.
Functions 103