Skip to content

Getting Started with Shell Programming

Published: at 12:00 AM
[vi]

Bash shell

Even though we are quite familiar with shell scripts, I still want to introduce how to write a shell script for those of you who need it.

Table of contents

1. How to write a shell script?

Step 1: Use any text editor. For example: vi

Step 2: After writing, grant execution permissions to the script. For example:

chmod u+x script_name

Step 3: Execute the script. Syntax:

bash script_name
sh script_name
./script_name

The structure of a shell script is as follows:

#!/bin/bash # <- the shell the script will run
command # <- command
command
exit 0 # <- exit

Note: The exit 0 command will be explained in detail in the Exit Status section.

2. Variables in the shell

In the Linux shell, there are two types of variables:

Variable definition: variable_name=value

  1. The name starts with a letter or underscore (_).

  2. No spaces before and after the equal sign when assigning a value to a variable.

  3. Variables are case-sensitive.

  4. You can declare a variable with a NULL value as follows: var01= or var01=""

  5. Do not use ?, * in variable names.

3. Using variables

To access the value of a variable, use the following syntax: $variable_name

Example:

n=10
echo $n
  1. echo command Used to display text, variable values, etc.

Syntax: echo [options] [string, variables…]

Options:

-n: do not print the trailing newline character.
-e: enable interpretation of backslash escapes in the string.
\a: alert (bell)
\b: backspace
\c: suppress trailing newline
\n: newline
\r: carriage return
\t: tab
\\: backslash

Example: echo –e "one two three \a\t\t four \n"

5. Arithmetic in Shell

Using expr

Syntax: expr operand1 <operator> operand2

Example:

expr 1 + 3
expr 2 1
expr 10 / 2
expr 20 % 3
expr 10 * 3
echo `expr 6 + 3`
x=4
z=`expr $x + 3`

Using let

Example:

let "z=$z+3"
let "z += 3"
let "z=$m*$n"

Using $((…))

Example:

z=$((z+3))
z=$(($m*$n))

Note:

expr 20 \% 3 # 20 mod 3
expr 10 \* 3 # multiplication, use \* instead of * to distinguish from the wildcard character.

The last line in the example above is commonly used in the shell; when a command is placed between two double quotes (not single quotes), the shell will execute that command.

Example:

a=`expr 10 \* 3`

–> a will have the value of 10 x 3 = 30 Print the result to the screen:

a=`expr 10 \* 3`
echo $a
30

6. Some information about double quotes

There are three types of quotes:

": Double quotes, anything within double quotes is treated as separate characters.
‘: Single quotes, anything within single quotes remains unchanged.
`: Backticks, execute the enclosed command.

Example:

echo "today is date" # will not print today is what day
echo "today is `date`" # will print today's date because date is within backticks ` `

7. Exit Status

By default, in Linux, when a command or script is executed, it returns two types of values to determine whether the command or script was executed successfully.

  1. If the return value is 0 (zero) -> the command was successful.
  2. If the return value is non-zero -> unsuccessful.

This value is called the Exit Status.

So how do you find out the return value of a command or script?

Very simple, just use the special shell variable: $?

Example: If you delete a non-existent file on the hard drive

rm unknown_file
echo $? -> will print a value other than 0

8. read command – read input from the keyboard, file, etc.

Used to get input from the keyboard and store it in a variable.

Syntax: read var1 var2 var3 … varN

read without parameters -> the value will be stored in the $REPLY variable.

Example:

read
var="$REPLY"

Normally, the backslash \ allows line breaks to continue entering data in read. If read –r is used, it will have no effect.

Example:

read var
first line \
second line
echo "$var"
first line second line # <- result

What about with the -r parameter?

read –r var
first line \
echo "$var"
first line \

The read command can be used to read from a file. If the file contains more than one line, only the first line will be assigned to the variable.

If read has more than one variable (read var1 var2 …), read will rely on the $IFS variable to assign data to the variables.

By default, $IFS is a space.

Example:

read var < data_file

If the file has more than one line

read var1 var2 < data_file

In this case, each variable will contain a string separated by a space $IFS, not an entire line. The last variable will contain the rest of the line.

So how do you read the entire file? Can it be solved with a loop?

while read line
do
  echo $line
done < data_file

Use $IFS (Internal File Separator) to separate an read input line. If you don’t want the default to be a space, what do you do?

Look at the following script:

echo "list all users"
OIFS=$IFS; IFS=: # backup IFS and assign a new value. For /etc/passwd file, use : to separate

since the fields are separated from each other, assign IFS to:

while read name passwd uid gid fullname ignore
do
  echo "$name $fullname"
done < /etc/passwd # I/O redirection
IFS

=$OIFS # restore the initial IFS

If you set IFS right inside the loop, there is no need to back up IFS

while IFS=: read name passwd uid gid fullname ignore
do
  echo "$name $fullname"
done < /etc/passwd

IFS remains unchanged

9. Command parameters

Let’s say we have a script named myself, to execute this script, we need to pass in 2 parameters like this:

myself one two

In which

myself: script name
one: the first parameter passed to the script
two: the second parameter

In the shell, you access these parameters as follows:

myself: $0
one: $1
two: $2

And the variable $# (available in the shell) will have the value 2 (with 2 parameters one and two).

You can retrieve all parameters using the $@ or $* variables.

10. Redirection

Most commands output results to the screen or take input from the keyboard, but with Linux, you can also redirect output to a file and read data from a file.

For example:

ls > filename # print the results of the ls command to a file named filename

There are 3 redirection symbols >, >>, and <.

  1. Symbol >

Syntax: linux-command > filename

Output the command’s output to a file. If the file already exists, it will overwrite it, otherwise, it will create a new file.

  1. Symbol >>

Syntax: linux-command >> filename

Append the output of the command to the end of the file if the file already exists, otherwise, it will create a new file.

  1. Symbol <

Syntax: linux-command < filename

Get data for the linux-command from the filename instead of from the keyboard.

11. Pipe

Syntax: command 1 | command 2 The output of command 1 will be the input of command 2.

For example:

who | grep root

Conclusion

These are some basic syntax examples that I hope can help you, at least a little :D

Translated from Vietnamese version by ChatGPT