Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
December 22, 2021 03:06 am GMT

Bash Scripting Concepts: Part 1 of 2

Overview

Bash is a tool that provides a text-based user interface for managing operating system resources. It's also the run-time environment for a simple interpreted programming language that can be used to create scripts for automating tasks.

Bash is the evolution of the popular Born Shell (sh), a de facto standard among Unix-like operating systems. It provides all the features of its predecessor plus a new set of built-ins and configuration settings.

Using Bash

There are three common use cases for Bash:

  • User shell: configured at the operating system level, provides the shell for user login, either local or remote.
  • Script run-time: provides the execution run-time for Bash scripts
  • Temporal shell: provides an interactive shell session on top of the user shell. The new session is a sub-process of the actual user or a different user when using privilege delegation tools such as SuDO.

This tutorial will focus on the scripts run-time use case.

Script structure

Bash scripts are text files describing a sequence of commands:

  • Commands can be either built-in or external Linux apps.
  • Commands are separated from each other by the new-line character (standard line separator for Linux/Unix systems).
  • Long lines can be split using the scape character \
  • Commands can be grouped on the same line using the semicolon separator ;
  • Commands and arguments are separated using one or more spaces.
  • Although not required, it's recommended that the first line of the script contains: #!/bin/bash
  • Script files must have execution and read permissions if used directly, or just read-only permissions if called using Bash.

For example:

#!/bin/bashecho 'echo and printf are built-in commands'printf 'pwd is an external Linux command that shows the current directory: 'pwdprintf 'multiple '; printf 'commands '; printf 'on the same line
'
printf '%s %s %s
'
\ 'single command' \ 'using multiple' \ 'lines'

Using Variables

Declaration

Variables in Bash are created using a declaration command and the equal = symbol to associate the variable name to its value. Notice that there should be no spaces before and after the assignment symbol:

declare variable_name='variable value'

Bash provides the following built-in commands for declaring variables:

CommandUsageScope
exportDeclare global variablesScript-wide and sub-processes
readonlyDeclare readonly variables (constants)Script-wide
declareDeclare script level variablesScript-wide
localDeclare function level variablesFunction-wide

Consider the following best practices:

  • Declare variables at the beginning of the code block.
  • Declare and initialize all the variables that the script will use.
  • Readonly and exported variables should be named using all uppercase.
  • Use single quotes for static content.

Retreive variable's value

To use the value of a variable, prepend the dollar symbol $ to the name of the variable surrounded by brackets {}.

As a best-practice, surround variable expansion with double quotes:

echo "${test_variable}"

Bash also provides processing functions that can be used for altering the value before the expansion.

For example:

#!/bin/bashdeclare var1='word1'declare var2='WORD2'declare var3='AbCdE/12345'printf 'replace value with its length: "${#var1}" = "%s"
'
"${#var1}"printf 'right strip from pattern: "${var3##*/}" = "%s"
'
"${var3##*/}"printf 'left strip from pattern: "${var3%%/*}" = "%s"
'
"${var3%%/*}"printf 'convert to uppercase: "${var1^^}" = "%s"
'
"${var1^^}"printf 'convert to lowercase: "${var2,,}" = "%s"
'
"${var2,,}"

Data Types

Bash supports four data types:

TypeDeclaration command
stringdeclare
integerdeclare -i
arraydeclare -a
associative arraydeclare -A

Even though there is no explicit boolean data type, Bash interprets the exit status of commands as:

  • exit status == 0: true
  • exit status > 0: false

Parameters

Parameters are special variables that are automatically created when a function or script is called with arguments.

The variable name is created by using a single number to represent the position of the word in the argument list:

bash say_hello.bash 'to' 'my' 'little' 'friend'

#!/bin/bashdeclare msg1="$1" # Variable $1: assigned to the first variabledeclare msg2="$2" # Variable $2: assigned to the second variabledeclare msg3="$3" # Variable $3: assigned to the third variabledeclare msg4="$4" # Variable $4: assigned to the forth variableprintf 'say hello %s %s %s %s
'
"${msg1}" "${msg2}" "${msg3}" "${msg4}"

Shell Expansion

In addition to variables Bash provides additional features for generating dynamic values:

  • $( ): Command Expansion: Execute the command in a sub-process and expand its STDOUT.
  • $(( )): Arithmetic Expansion: Evaluate the arithmetic expression and use the resulting value for the expansion.
  • $(< ): File Expansion: Read the content of a file and use it for the expansion.

For example:

#!/bin/bashprintf 'Command Expansion: "$(echo hello-world)" = "%s"

'
"$(echo 'hello-world')"printf 'Arithmetic Expansion: "$(( 2 + 2 ))" = %s

'
"$(( 2 + 2 ))"printf 'File Expansion: "$(</etc/os-release)"
%s
'
"$(</etc/os-release)"

Working with processes

Before going into the details, let's review the following key concepts about Unix processes:

  • A process is a running app that is executed from an already running process (parent). For scripts, the parent process is the one running the Bash run-time.
  • The Operating System assigns unique integer identifiers to each process (PID: Process ID).
  • Processes have 3 data paths:
    • STDIN: standard input: process can read data from this path.
    • STDOUT: standard output: process can write data to this path.
    • STDERR:: standard error: process can write error diagnostic data to this path.
  • Exit status: numeric value that represents the final execution status of the process. In general:
    • 0: successful execution
    • >0: failed execution. The app can assign different numbers to further describe the error.

Bash provides the following features for interacting with processes:

  • Variables: show process information
    • $?: exit status of the last executed command
    • $BASHPID: PID of the current Bash process
  • Redirection: redirect the data flow from the STDIN, STDOUT, and STDERR
  • Pipelines: integrate two processes by creating a pipe between the STDOUT from one to the STDIN of the other

Additional features are available but no covered in the current tutorial (jobs, signals, traps, parallelism, etc.)

Implementing Functions

To declare a function in Bash use the following structure:

function <FUNCTION_NAME>() {  <COMMANDS>  return <EXIT_STATUS>}

Functions in Bash behave in a similar way to scripts and commands:

  • Can be called directly from the script or command line
  • Use positional parameters that are automatically assigned to $N variables
  • Have exit status
  • Can send data to STDOUT and STDERR
  • Can receive data from STDIN
  • Can be used in complex command sequences (&&, ||, |)

Let's create a function with all the concepts seen so far:

#!/bin/bashreadonly TEST_READONLY='content of this variable is constant and can not be modified afterwords'export TEST_EXPORT='content of this variable is visible everywhere'declare test_declare='this variable is declared at the script level'declare -i function_result=0function test_function() {  local test_parameter="$1"  local test_parameter_default="${2:-default-value}"  local test_local='this variable is available only inside this function'  local test_static=''  # initialize a static variable  local test_dynamic='' # initialize a dynamic variable  test_static='this variable has static content'  test_dynamic="$(echo 'this dynamic variable is assigned at execution time')"  printf 'Show variable content from inside a function:

'
printf ' first parameter: [%s]
'
"${test_parameter}" printf ' second parameter, default value: [%s]
'
"${test_parameter_default}" printf ' local static variable: [%s]
'
"${test_static}" printf ' local dynamic variable: [%s]
'
"${test_dynamic}" printf ' exported variable: [%s]
'
"${TEST_EXPORT}" printf ' readonly variable: [%s]
'
"${TEST_READONLY}" printf ' declared variable: [%s]
'
"${test_declare}" return 5}test_function 'this value is assigned to the first parameter'function_result=$?printf '
Show the same variables but outside the function:

'
printf ' local variable: [%s]
'
"${test_local}" printf ' local static variable: [%s]
'
"${test_static}" printf ' local dynamic variable: [%s]
'
"${test_dynamic}" printf ' exported variable: [%s]
'
"${TEST_EXPORT}" printf ' readonly variable: [%s]
'
"${TEST_READONLY}" printf ' declared variable: [%s]
'
"${test_declare}"printf '
Show the exit status (return value) of the function: [%s]
'
"${function_result}"printf '
Show current PID of the Bash run-time: [%s]
'
"${BASHPID}"

Next Steps

Continue reading the second part of the tutorial: Bash Scripting Concepts: Part 2 of 2

Copyright information

This article is licensed under a Creative Commons Attribution 4.0 International License. For copyright information on the product or products mentioned inhere refer to their respective owner.

Disclaimer

Opinions presented in this article are personal and belong solely to me, and do not represent people or organizations associated with me in a professional or personal way. All the information on this site is provided "as is" with no guarantee of completeness, accuracy or the results obtained from the use of this information.


Original Link: https://dev.to/serdigital64/bash-scripting-concepts-part-1-of-2-28fk

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To