Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
20 views

Shell Scripting Notes

Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Shell Scripting Notes

Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

if

==

if [ <condition> ]; then
<logic>
elif [ <condition> ]; then
<logic>
else
<logic>
fi

for loop
========

for <variable> in <list>; do


<logic>
done

while loop
==========

while [ condition ]; do
<logic>
done

string in bash
==============

Every variable in bash is treated as variable of type string.


Therefore,

test_var=10
test_var+=20
output: 1020

To interpret values as integers,

test_var=10
test_var=$(( test_var+=20 ))

To execute linux commands and save the result to variable


==========================================================

var=$(command 1 | command 2 | ... | command n)

To retrieve the value of a variable


===================================

${var}

To check if a variable is empty or not


======================================

if [ -z ${var} ] # to negate the logic if [ ! -z ${var} ]


Special Variable in bash
========================

$0 - represents the name of the function


$1, $2, ... - represents the arguments of the function
$# - represents the number of arguments to a function
$@ - represents the list of arguments to a function as separate quoted strings
( which are stored in $1, $2 etc.) You can iterate through the list.
$? - represents the exit status of command last executed. 0 is success.
$$ - represents the process ID of the current script.
$!: Captures the PID of the last background process started in the background using
&.

Example:
Multiple inputs
===============

#!/bin/bash (or #! /usr/bin/env bash )

echo "Number of arguments: $#"


echo "Arguments passed: $@"

# Loop to display each argument separately

for arg in "$@"; do


echo "Argument: $arg"
cd "${target_directory}" || exit << command 1 OR command 2. This
means if command 1 fails what is the command to execute ( which is command 2 )
done

If you run this script as ./script.sh arg1 arg2 arg3, the output will be:

Number of arguments: 3
Arguments passed: arg1 arg2 arg3
Argument: arg1
Argument: arg2
Argument: arg3

Single input
============

# Check if a directory path argument is provided

if [ $# -ne 1 ]; then
echo "Usage: $0 <directory_path>"
exit 1
fi

# Use the provided directory path

target_directory="$1"

# Move to the specified directory

cd "${target_directory}" || exit ( or cd "$


{target_directory}" || continue etc)
Defining a function

===================

func_name() {
<commands>
}

eg:
send_email() {
echo -e "$body" | mail -s "$subject" "$recipient"
}

Break from script for condition


===============================

exit 1 ( any non-zero exit code )

Extract a specific set of records from the result


=================================================

a) using head and tail

tail -n 8 | head -n 5 # tail implies start from 8th line till end.
head will strip off first 5 lines from that.

b) using awk

awk 'NR>=8 && NR<=13' # same result as above

To filter only one line ( or all matching lines for a keyword )from the result of a
command output

===================================================================================
===============

use grep command.

Eg: top -b -n 1 | grep "%Cpu"

To sort results

===============

Example:

file_group_list=$(ls | sed -E 's/([a-z]+)([0-9]+).([a-z]+)/\1.\3/' | sort)

To sort and list only unique elements

file_group_list=$(ls | sed -E 's/([a-z]+)([0-9]+).([a-z]+)/\1.\3/' | sort -


u)

Record processing using AWK


===========================

1. To Extract a set of records from the input

awk 'NR>=8 && NR <=18'

2. To extract the column values

First identify the Field delimiter and then use it ( default is space).

awk -F ',' '{print $2}' # $1, $2 etc holds the extracted columns

3. You can use BEGIN logic to do some pre-processing ( like creating column headers
for printing the data).

Eg: top -b -n 1 | awk 'BEGIN {printf "| %-8s | %-8s | %-8s | %-8s | %-8s | %-8s |
%-8s | %-8s | %-8s | %-8s |\n", "PID", "USER", "%CPU", "%MEM", "TIME+", "COMMAND",
"PID", "USER", "%CPU", "%MEM"} NR>7 && NR<=17 {printf "| %-8s | %-8s | %-8s | %-8s
| %-8s | %-8s | %-8s | %-8s | %-8s | %-8s |\n", $1, $2, $3, $4, $5, $6, $7, $8, $9,
$10}'

Text processing and pattern matching using SED ( stream Editor)


================================================================

SED (Stream EDitor) is a powerful command-line tool used for text manipulation in
Unix and Linux environments. It processes text line by line, applying specified
operations to the input stream (or files) and producing the modified text as
output.

Examples:

1.
sed 's/milk/soy milk/' data001.txt

# meaning: substitute the word milk ( both independent and part of


another word ) with the word 'soy milk'. Only the first occurance of the word in
each line is modified and it is case-sensitive.

# file is not directly modified. but SED keeps the modified file in
it's own space.

2. In the above case, to change all occurance of the word in a line, make the
substitution global.

sed 's/milk/soy milk/g' data001.txt

3. To make the change case-insensitive,

sed 's/milk/soy milk/Ig' data001.txt

4. To modify the file directly,

sed -i 's/milk/soy milk/Ig' data001.txt

5. To substitute only the words that are not part of another word; use word
boundaries (\b)

sed -i 's/\bmilk\b/soy milk/Ig' data001.txt


6. To delete a word from the file;

sed '/pattern/d' filename

To delete empty lines from the contents of a file,

sed -i '/^$/d' data001.txt

7. To print lines between two linesmatching some patterns;

sed -n '/start_pattern/,/end_pattern/p' filename

sed -n '/banana/,/coffee/p' data001.txt

8. To replace multiple spaces in a line with single space in all lines.

sed -i 's/ \+/ /g' data001.txt

But the best way is to use extended regex where ever possible.

sed -i -E 's/ +/ /g' data001.txt

9. Random combination of valid strings, numbers etc and operations based on that.

eg:

file_group_list=$(ls | sed -E 's/([a-z]+)([0-9]+)\.([a-z]+)/\1.\3/' | sort -


u)
echo ${file_group_list}

# Observation: While using differnt regular expression tools like sed, awk, grep,
cut etc, you should know how each group of the result is addressed.
# In the case of awk, grep, cut etc , each group of result is stored in
$1, $2, $3 ... etc.
# In the case of sed, the results are stored in \1, \2, \3 etc. You
also need to understand, the results of any expression evaluations are only stored.

# For example, in the below sed command, there is only one regex in the
pattern to be matched. other part is just variable expansion. Hence the evaluated
result is stored in \1.

number_part=$(echo "${filename}" | sed -E "s/${string_part}


([0-9]+).${extension}/\1/")

# Special characters have special meaning in shell when they are not escaped. If
they are escaped, no special meaning and treated as a string ( Exception is when
using -E with sed. Special charater meaning can be retained in this case without
using escapes )

[[ <condition ]] operation
==========================

# If you're writing scripts specifically for Bash, using [[ ... ]] is generally


acceptable and provides additional features compared to [ ... ].

# [[ ... ]] is newer and applicable only in shells that support them. The [[ ... ]]
construct in Bash is an extended test command. It provides additional features
compared to the [ ... ] (single square # brackets) test command, including support
for pattern matching and additional logical operators.

Examples:
=========

1. if [[ "$variable" == "value" && "$other_variable" != "other_value" ]];


then
# Code to execute if the condition is true
fi

2. if [[ "$string" == *pattern* ]]; then


# Code to execute if the pattern is found in the string
fi

3. if [[ "$string" =~ ^[0-9]+$ ]]; then


# Code to execute if the string contains only digits
fi

4. if [[ "$value" == "A" && "$status" -eq 1 ]]; then


# Code to execute if both conditions are true
fi

5. if [[ "$string1" < "$string2" ]]; then


# Code to execute if string1 is lexicographically less than string2
fi

6. while [[ "$condition" == "true" ]]; do


# Code to execute while the condition is true
done

7. until [[ "$count" -ge 10 ]]; do


# Code to execute until the condition is true
((count++))
done

8. case "$variable" in
"value1")
# Code for value1
;;
"value2")
# Code for value2
;;
*)
# Default case
;;
esac

9. if [[ $((num % 2)) -eq 0 ]]; then


echo "Even"
else
echo "Odd"
fi

10. As standalone condition check.

[[ "$string" == "pattern" ]] && echo "Match" || echo "No match"


case statement Examples:
========================

1.

#!/bin/bash

fruit="apple"

case "$fruit" in
"apple")
echo "Selected fruit is Apple"
;;
"banana")
echo "Selected fruit is Banana"
;;
"orange")
echo "Selected fruit is Orange"
;;
*) # Default case if none of the patterns match
echo "Unknown fruit"
;;
esac

2.
#!/bin/bash

score=85

case $score in
90|91|92|93|94|95|96|97|98|99|100) ( or use can use {90..100} )
echo "A"
;;
80|81|82|83|84|85|86|87|88|89)
echo "B"
;;
70|71|72|73|74|75|76|77|78|79)
echo "C"
;;
60|61|62|63|64|65|66|67|68|69)
echo "D"
;;
*)
echo "F"
;;
esac

3.

#!/bin/bash

file="example.txt"

case "$file" in
*.txt)
echo "Text file"
;;
*.jpg|*.jpeg)
echo "JPEG image"
;;
*.png)
echo "PNG image"
;;
*)
echo "Unknown file type"
;;
esac

4.

#!/bin/bash

day="Monday"

case "$day" in
"Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday")
echo "Weekday"
;;
"Saturday" | "Sunday")
echo "Weekend"
;;
*)
echo "Invalid day"
;;
esac

You might also like