DEV Community

Cover image for Linux shell scripting for beginners
Kevin Naidoo
Kevin Naidoo

Posted on • Updated on

Linux shell scripting for beginners

As a full stack or backend developer, you will inevitably need to write some BASH; either to deploy or manage some aspect of your web apps. We are used to high-level languages such as TypeScript, Python, PHP, and so forth. When it comes to writing BASH, it can be such a pain to even do basic tasks.

In this guide - I will cover some of the common concepts in the bash scripting language that will hopefully make your Linux scripting a little less painful.

NOTE: these should work on BASH shells you commonly find on distro's such as Ubuntu, however not all statements are strictly POSIX complaint. Learn more about POSIX here.

1) IF statements

x=1

if ((x==2)); then
  echo "$x = 2"
fi

if ((x>0)); then
  echo "$x > 0"
fi

if ((x<=1)); then
  echo "$x <= 1"
fi

Enter fullscreen mode Exit fullscreen mode

The above is an IF statement that performs arithmetic comparisons. We use "(())" double round brackets to ensure that the parser treats this as a mathematical comparison.

One problem though with this approach; they don't play nice with floating point numbers. You will get a weird error similar to:

test.sh: line 2: [: 1.50: integer expression expected

Luckily, BASH comes with a handy library "bc" - that can handle more advanced math. Here is an example below:

if (( $(echo "$x < 3.25" | bc -l) )); then
  echo "$x is less than 3.25"
fi
Enter fullscreen mode Exit fullscreen mode

This command will essentially return 1 or 0, and then we use the regular arithmetic IF to test if this is true i.e. "1".

$(echo "$x < 3.25" | bc -l)
Enter fullscreen mode Exit fullscreen mode

The "-l" option we pass to bc basically just "imports" all the essential math functions needed.

For comparing strings - you can use square brackets. Actually, you can also use square brackets to compare numbers as well:

if [ "hello world" = "world" ]; then
    echo "Yes, this is true."
else
    echo "No, this is false."
fi

if [ "$a" -gt "$b" ]; then
     echo "Yes $a is greater than $b."
fi

Enter fullscreen mode Exit fullscreen mode

2) Lists

To declare a list in BASH:

countries=("South Africa" "Japan" "China" "United States")
Enter fullscreen mode Exit fullscreen mode

One thing that can trip you up, is the delimiter between each item. Normally in most languages, we use a "," to separate items however in bash it's just a space.

To loop through the list:

countries=("South Africa" "Japan" "China" "United States")
for country in "${countries[@]}"; do
  echo $country
done
Enter fullscreen mode Exit fullscreen mode

When looping through lists, be careful not to forget the quotes in the following line:

for country in "${countries[@]}"; do
Enter fullscreen mode Exit fullscreen mode

Leaving out the quotes will incorrectly interpret all spaces and print the following:

South
Africa
Japan
China
United
States
Enter fullscreen mode Exit fullscreen mode

3) Maps

declare -A profile
profile[name]="Kevin"
profile[country]="South Africa"
profile[website]="https://plexscriptables.com"

echo  "Name: ${profile[name]} , Website: ${profile[website]}"
Enter fullscreen mode Exit fullscreen mode

You can also loop through the map:

declare -A profile
profile[name]="Kevin"
profile[country]="South Africa"
profile[website]="https://plexscriptables.com"


for key in "${!profile[@]}"; do
    echo "$key : ${profile[$key]}"
done
Enter fullscreen mode Exit fullscreen mode

4) Functions

gotoServer () {
   local user=root
   ssh $user@$1
}

gotoServer 192.168.1.1
Enter fullscreen mode Exit fullscreen mode

A few important points to note when using functions:

  • They can access variables from outside the function.
  • use "local" in front of the variable name to limit the scope of the variable to your function.
  • Functions don't expect arguments to be defined as with other languages. Anything after the function name when called will automatically be available in positional variables: $1,$2,$3, and so forth.

5) Running DB queries (MySQL)

sql_query="SELECT TABLE_NAME,DATA_LENGTH FROM  TABLES;"
result=$(
    mysql -ukevin -p1234 information_schema -e "$sql_query"
)

IFS=$'\n'
for row in $result; do
  IFS=$'\t' read -a cols <<< "$row"
  echo "Table Name: ${cols[0]}, Data Length: ${cols[1]}"
done
Enter fullscreen mode Exit fullscreen mode

In the about we are effectively fetching rows from the database and printing them out.

You will notice we set a variable before the for loop:

IFS=$'\n'
Enter fullscreen mode Exit fullscreen mode

The MySQL command will essentially return text. IFS (internal field separator) will cause the loop to read the MySQL output line by line. This is similar to the "split" or "explode" functions in other languages.

IFS=$'\t' read -a cols <<< "$row"
Enter fullscreen mode Exit fullscreen mode

In the above: "read -a cols" - is similar to a loop, it'll split each row by the tab character and the "-a" flag basically creates a variable with a type of "array".

Conclusion

BASH is weird, its syntax is overly cryptic. I guess this is so because of its origins being in the 80s before all the cool modern tooling was invented.

Nonetheless, it's a powerful tool in your arsenal, to quickly run short scripts and, will make you super productive in your terminals, without needing to write a full script in Python or Perl.

Top comments (0)