Linux Bash Scripting Tutorial
Variable is given a name it to a memory location. Variable has a value and zero or more attributes. variables can be aasigned with numbers or strings or special characters in shell. variables are nothing but shell variables or user defined variables in shell Bash variables can be
Declaring variables in Bash shell Syntax
untyped variable variable=[value] #untyped variables typed variable declare -i i=100 #typed variable of integer declare -r k=100 #readonly variable, must be intialized declare -a aa; #array variable
There are 3 different types of parameters:
Untyped variable values considered as string literal. No prior declarion required for untyped variables
Setting value to a untyped variable
variable=[value]
*optional [value] is set , value stored in variable. if not set null will be assigned to variable.
for ex:
x=10 ; //Number 10 assigned to variable x
name="sam" ; //String sam assigned to variable name
pwd=~; //special character tilde~ assigned to variable pwd.
p= //null value assigned to variable p
y=10+10; // 10+10 treated as a string .
z = 100; // error, here bash considers z is a command and parameters are = and 100.
// No space should be given before and after equal sign.
Prior declaration is required for typed variables using declare command
declare syntaxdeclare [options] [name[=value]] declare -i x=10; // here x is declared as integer variable. declare -i x=10+10; // Right Hand side(RHS) treated as arithmetic expression. value of x evaluated to 20. //declaring multiple variables declare -i x=20 y=20 declare -i x=20 y=20 z=x+y //here z has sum of x and y
Options | Description |
---|---|
-i | each variable is integer,in an assigment,,the value is evaluated as arithmetic expression |
-A | declaring associate arrays |
-a | declaring indexed array |
-r | Marking variables as readonly, readonly variables should be assigned at the declarion |
-x | Mark variables exported into sub shells/processes. |
-f | Each name is function. |
Variable values can be accessed in 2 different ways
for ex: x=10 echo $x //displays value x.
for ex: x=10 echo ${x} //displays value x. This is prefered way for displaying array elements $ ~> echo ${a[@]} #here a is array variable
$ ~> declare -r PI=3.14159
$ ~> PI=2.789
bash: PI: readonly variable
$ ~> unset PI;
bash: unset: PI: cannot unset: readonly variable
readonly variables once set,programmer cannot unset or assign a new value. Scope of the read only variable will be from where it is declared to end of the file.
Bash allows indirect look-up using prefix ! operator
That is, ${!var} behaves like a ${${var}}
name=age age=42 echo ${!name} #prints 42 age=(10 20 30 40 50 60 70) agelimit=age[1] echo ${!char} #prints 20
Variable value can be unset using unset command
x=100
name="samuel"
echo $x, $name //displays 100,samuel
unset x
unset name
echo $x, $name //displays only comma(,), both variables set to null
Unsetting multiple variables
unset x name // removes x and name values and assigns them with null value.
Removing all Array Elements
$ ~> a=(1 2 3 4 5 6) //set values for array variable a
$ ~> echo ${a[*]} //Displays array values
1 2 3 4 5 6
$ ~> unset a //removes all values from array a
$ ~> echo ${a[*]} // array a set to null
The "$" parameter introduces shell parameter expansion. "$" followed by variable name,performs variable expansion.
$ ~>i=10 $ ~>echo $i #here echo command does parameter expansion , before displaying output on console. 10
$ ~> name="sam"
$ ~> echo $name #parameter "name" expanded first , then result will be displayed on screen.
#if u want to append some text to variable, for ex: "name" variable append "firtsname"
$ ~> echo $namefirstname #display empty string or set to null,
#because its looking for variable called namefirstname,
#that's not defined,anywhere in the program.
#To solve this $ with curly braces with variable name in it.
${Variable} i.e ${name}firstname
#displays "samfirstname"
#insert some space between name and firstname string
${name}' 'firstname
sam firstname
Parameter Expansion in double Quotes,Single Quotes and Back Quotes
$ ~> i=10 $ ~> echo "${i}" Double quotes does parameter expansion 10 $ ~> echo '${i}' Single quotes does not expand parameter ${i} $ ~> cmd=ls; Back quotes does parameter expansion $ ~> echo `${cmd}` #variable cmd set to "ls" command #back quotes does command substitution. #echo command first performs variable substitution, then back quotes expands command. #list of files in the current directory will be displayed.
Displays string from specified position
var="Hello This is text message"
echo ${var3:5}
This is text message
Note:pos can start from 0, 0 means entire string.It can even be negative values, -1 means last character
echo ${var3: -7} ;gets last 7 characters,i.e reading from right to left.
message Note:There should be space between colon and number for -ve values
Extracts substring from string, pos is starting index, length is pos+length
var="Hello you got text message" echo ${var:10:8} got text ; here 10th position has character 'g' from there to next 8 characters including 'g' . i.e "got text"
Finds length of the variable
var="samsung" echo ${#var} 7
Use parameter value if it is set otherwise use "value"
;first case var1 set to null. var1= echo ${var1:-"World"} ; displays "world" World //second case var2 is set var2="hello" echo ${var2:-"World"} //variable value will be displayed ,ignores value "world" hello
use value if var is set, otherwise do nothing
var="Hello you got text message" echo ${var:+"nothing"} ; uses value i.e "nothing" because var is set, this is quite opposite to ${var:-value} nothing
Use variable if it set, if it is not set display value and then assign value to variable
;first case var1 set to null. var1= echo ${var1:="World"} ; displays "world" World echo ${var1} ; var1 is has value "World" World //second case var2 is set var2="hello" echo ${var2:="World"} //variable value will be displayed ,ignores value "world" hello
Use var if set; otherwise, print value and exit (if not interactive). If value isn’t supplied, print the phrase parameter null or not set to stderr.
Removes shortest matching piece from Right
$ v='abc.def.ghi.klmn' # '.klmn' shortest matching piece from right $ echo ${v%.*} abc.def.ghi
Removes longest matching piece from Right
$ v='abc.def.ghi.klmn' # '.def.ghi.klmn' longest matching piece from right $ echo ${v%.*} abc
Removes shortest matching piece. Use the value of parameter after removing text matching pattern from the left
$ v='abc.def.ghi.klmn' # 'abc.' shortest matching piece from left $ echo ${v#*.} def.ghi.klmn
Removes longest matching piece.
$ v='abc.def.ghi.klmn' # 'abc.def.ghi.' longest matching piece $ echo ${v##*.} klmn
Finds a given pattern and replaces with 'repl' string. if pattern not found unalters the text
example:1 $->s='you got a phone call' $->echo ${s/got/received} you received a phone call. In the above example 'got' is a pattern being replaced by 'received' example 2: $->var="numbers are 1 2 3 4 5 6" $->echo ${var/numbers are/} 1 2 3 4 5 6 Pattern:numbers are Replacement Text: is empty; The above example replaces 'numbers are' pattern with empty text.
Removes given pattern in a variable.
$ $ v=100_100_100_100 $ echo {v/_} #remove first occurance of the underscore(_) symbol from variable v 100100_100_100${parameter//pat} # removes all occurance of pattern in the parameter(left to right).
$ $ v=100_100_100_100 $ echo {v/_} #remove all occurance of the underscore(_) symbol from variable v 100100100100
Finds and replace the pattern.
Following example finds the all space character replaces with Underscore character,As shown below
$ amex='3712 345678 95006' $ $ echo ${amex// /_} 3712_345678_95006
Finds pattern and replaces till it reaches last character in the pattern(left to right)
mask off credit card number: it looks for last space character. pattern: '* ' means it skips all characters until it reaches last space character, replaced with given replacement text/character(s).$ echo $amex 3712 345678 95006 $ echo ${amex/#* /***********} ***********95006
Finds pattern and replaces till it reaches first character in the pattern(right to left)
mask off credit card number: it looks for first space character(right to left). pattern: ' [0-9]*' means it skips all characters until it reaches first space character, replaced with given replacement text/character(s).$ echo $amex 3712 345678 95006 echo ${amex/% [0-9]*/********************} 3712********************
Indirect reference to variable 'paramater' , This is equal to ${${parameter}}
$ v='country' $country='INDA' #variable v contains another variable country, ${!v} displays value of referenced variable, instead of original variable's value $echo ${!v} INDIA
Exporting a variable can be done in 2 ways
Variable exported using any of the above commands will be visible to all sub-shells,otherwise variable is undefined,set to null value
$ ~> export x=10; $ ~> declare -x x=10;**variables exported using export and declare -x commands will be available to all script files.
export variable example:
$ ~> export x=10 $ ~> y=20 $ ~> cat exp.sh echo "x value:$x,y value:$y" $ ~> ./exp.sh
output: x value:20,y value:
y value is null, y is not visible to subshells
Shell treats several paramters specially. These are read-only paratemeters. Values set by bash shell , user canot modify these variables.
Character | Description |
---|---|
$* | All Arguments of the command-line. "$*" All arguments are quoted as "$1 $2 ...${10}" based Internal Field Seperator(IFS),IFS default set to space character |
$@ | All Arguments of the command-line. "$@" arguments are individually quoted "$1","$2"..."${10}" |
$# | Number of positional parameters or command line arguments |
$? | exit status of the most recently executed foreground pipeline. |
$- | Flags passed to the script(using set) |
$$ | Process ID of the shell |
$! | Process Number of the last background command |
$0 | Displays Shell Script name or command |
$_ | Has Pathname of the script.Later stores last argument of the previous command. |
Displaying process id using $$ special parameter.
$ ~> echo $$ #displays current shells process id.
calling $$ in script files will display different process id,beacuse each script file runs in sub-shell,unless specified source command.
$0 parameter displays shell script name or command.
displays shell name
$~> echo $0 bashwith in the script example.sh
#!/usr/bash echo $0 echo `basename $0`./example.sh
Displays number of arguments passed to script file
for ex: script.sh 1 2 3 4 5 6echo "Number of arguments passed: $#"output will be "Number of arguments passed: 6
if [[ $# -ne 1 ]] ; then echo "Number of arguments must be 1"; exit 1; fiExecuting Script file
$ ~> ./weather.sh or $ ~> ./weather.sh 19.99 NYif number of arguments are 0 or more than 1 ,displays message "Number of arguments must be 1"; and exits from script execution
All arguments in the command-line "$1,$2,$3...$N"
"$*" All Arguments in the command-line are treated as one string. "$1,$2..$N".The values are seperated by first character in the $IFS,internal field seperator
"$@" All Arguments in the command-line,are individually-Quoted "$1","$2".."$N"
exit status of the most recently executed foreground pipeline.
for ex:$ ~> ls # ls command displays list of files and directories. $ ~> echo $? # displays 0 0 means command execution is successful otherwise failed
Flags passed to the script(using set)
$ set 'uname -a' 'ls' 'pwd' $ echo $- pwd #last command/value assigned to $-
Process number of the last background command. for ex running gedit text editor in the background.
running gedit process in the background (append ambersand symbol & ) at the end.
$~>gedit&
then issue echo $! displays process number of the last background job (here gedit)
Initially it has script name, later stores last argument of the previous command
$ echo $ $echo $_ echo # last command without arguments 2nd example: find *.sh files in the current directory,, $_ has last file in the list $ ls *.sh 1.sh 2.sh 3.sh $ echo $_ 3.sh #Find .sh files in the current directory and its sub-directories $ find . -iname '*.sh' -exec ls {} \; $ echo $_ ; #last command argument is ;
Variables declared within the function is called as local variables, Accessing a local variable outside function body is an error
Variables declared outside the function and within the bash script is called as Global variables
Please refer Functions Section , for Local and Global Variables usage
Bash has 4 prompting variables PS1,PS2,PS3 and PS4
PS2 is called as secondary prompt string. its default value is >
PS1
Primary Prompt String(PS1),
The set command serves 2 purposes: one is to set various shell options, second one is to reassign positional parameters $1,$2,$3...
Executing set command ,gives set of variables that exists in the current environment, local or exported.
$~> set BASH=/usr/bin/bash BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore: globasciiranges:histappend:interactive_comments:progcomp:promptvars:source path BASHRCSOURCED=Y BASH_ALIASES=() BASH_ARGC=([0]="0") BASH_ARGV=() BASH_CMDS=() BASH_COMPLETION_VERSINFO=([0]="2" [1]="8") BASH_ENV=/usr/share/Modules/init/bash BASH_LINENO=() BASH_REMATCH=([0]= .....
There is no way to reassign positional parameters.... Its a read-only variables...
You can use set command to change the values of positional parameters. if words are given as arguments to set command on the command line,the positional parameters $1,$2,... will be assigned to those words. The previous values stored in the positional parameters will be lost. With in the shell program, call this command
$~>set one two three $~>echo $1-$2-$3 one-two-three
To Protect against both of these problems occuring, use the -- option to set. This tells the set not to interpret any subsequenent dashes.
$~> set -- -1 -2 -3 $~> echo $(( $1+$2+$3); -6
Read command reads input from the standard input or from a file descriptor.
Read command splits the line into multiple fields, first word assigned to variable1,second word assigned to variable2 etc.,
Read command maintains 1:1 ration i.e number of fields vs number of variables specified
If number of variables are more than number of fields, remaing variables are set to null
If number of fields are less than fields, last variable has remaining fields.
If no variable is specified, value is stored in $REPLY shell variable.
Option | Description |
-a array | assign the words into indexed , index starts from 0, Check in Arrays section |
-d delimiter | continue reading until delimiter character read instead of new line |
-n chars | return after reading n chars, rather than waiting for new line. |
-p prompt | Prompt before reading the input |
-r | Raw mode, ignore \ as a line-continuation character |
-s | Do not echo input on terminal |
-t timeout | reading input from a terminal or pipe, if no data entered is entered after timeout seconds,returns 1, if preventes application fro hanging forever,or waiting for user input. |
-u fd | reads from file descriptor n,default is 0 |
$ read line This is first line #user entered data $ echo $line #user entered data stored in variable 'line' This is first lineRead First Name and Last Name
$ read first last jhon hayes $echo "$first $last" jhon hayesHalt Command Execution using Read command
$ read
read command halts the command execution in a program. whenever user presses a Enter key or enters some text then Enter key. in either case,flow continues execution. If User types some text then presses Enter key, text will be stored in $REPLY shell variable.
Prompt User before entering Text. It displays 'first name:' then waits for user input. once user enters text, text stored in variable first
$ read -p 'first name:' first first name: hayes $echo $first hayes
Read with File Descriptor(fd)
Read from a file,instead of standard Input Device. Assign a FD to a file using exec command
Assign some number as a File Descriptor to a file (choose other than 0,1,2)
Read command reads a single line at a time, i.e it reads until it reaches a new line character(\n), so In order to read all lines of a file,loops can be used,
Following example uses while loop to read lines. Once Read command reaches end of file(EOF),loop terminates.
We have file called file.txt$ cat file.txt This is First Line This is Second Line This is Third line
#assign file descriptor $ exec 3< file.txt $ while read -u 3 line do echo $line done #OUTPUT This is First Line This is Second Line This is Third lineNote: Before attempting this example, programmer must be familiar with IO-Redirections and Loops concepts
ADS