Advanced Shell Variable Operations

Variable Deletion and Replacement

Removing Prefix Patterns

Removing the shortest matching prefix pattern using #:

greeting="Hello World, Welcome to Shell"
echo $greeting
greeting_clean=${greeting#*or}
echo $greeting_clean

Removing the longest matching prefix pattern using ##:

greeting_long=${greeting##*or}
echo $greeting_long

String Substitution

Replace only the first occurrence using single /:

echo $PATH
modified_path=${PATH/sbin/SBIN}
echo $modified_path

Replace all occurrences using double //:

global_replace=${PATH//sbin/SBIN}
echo $global_replace

Variable Testing

Simple variable substitution with default values (less commonly used):

result=${input_expr-default}

If input_expr is undefined, result receives default. If input_expr has a value, result takes that value.

String Processing

Calculating String Length

Method 1 - Using parameter expansion:

length=${#sample}
echo $length

Method 2 - Using expr command:

length_val=`expr length "$sample_text"`
echo $length_val

Finding Substring Index Position

The index function splits the string into characters and returns the position of the first matching character:

sentence="programming is interesting"
pos=`expr index "$sentence" ing`
echo $pos

When searching for a nonexistent substring, it returns 1:

pos=`expr index "$sentence" xyz`
echo $pos

Matching Substring Length

Matches from the beginning (returns 0 if not found):

text="programming is interesting"
matched_len=`expr match "$text" interesting`
echo $matched_len

Matching from the start with wildcards:

matched_len=`expr match "$text" prog.*`
echo $matched_len

Substring Extraction

Method 1 - Extract from position to end (0-based indexing):

data="spark hadoop flink storm"
extracted=${data:10}
echo $extracted

Method 2 - Extract specific length from position:

extracted=${data:10:5}
echo $extracted

Method 3 - Extract last 5 characters:

extracted=${data: -5}
echo $extracted

Method 4 - Alternative syntax with parentheses:

extracted=${data:(-5)}
echo $extracted

Method 5 - Extract first 2 characters of the last 5:

extracted=${data: -5:2}
echo $extracted

Important: When using expr, indices start at 1. When using ${string:position}, indices start at 0.

Complete String Processing Script

Requirement:

Given: data="Data processing framework is Spark,Spark is a distributed computing system"

Create a menu-driven script that:

  • Displays the string value
  • Option 1: Print string length
  • Option 2: Remove all occurrences of "Spark"
  • Option 3: Replace first "Spark" with "Flink"
  • Option 4: Replace all "Spark" with "Flink"
  • Exit when user inputs q or Q

Implementation Plan:

  1. Define functions for each operation:
    • show_menu
    • calculate_length
    • remove_spark
    • replace_first
    • replace_all

Functions Implementation:

#!/bin/bash
#

data="Data processing framework is Spark,Spark is a distributed computing system"

show_menu()
{
    echo "********************************"
    echo "(1) Show string length"
    echo "(2) Remove all Spark occurrences"
    echo "(3) Replace first Spark with Flink"
    echo "(4) Replace all Spark with Flink"
    echo "********************************"
}

calculate_length()
{
    echo "${#data}"
}

remove_spark()
{
    echo "${data//Spark/}"
}

replace_first()
{
    echo "${data/Spark/Flink}"
}

replace_all()
{
    echo "${data//Spark/Flink}"
}

Main Script Logic:

#!/bin/bash
#

data="Data processing framework is Spark,Spark is a distributed computing system"

show_menu()
{
    echo "********************************"
    echo "(1) Show string length"
    echo "(2) Remove all Spark occurrences"
    echo "(3) Replace first Spark with Flink"
    echo "(4) Replace all Spark with Flink"
    echo "********************************"
}

calculate_length()
{
    echo "Length: ${#data}"
}

remove_spark()
{
    echo "${data//Spark/}"
}

replace_first()
{
    echo "${data/Spark/Flink}"
}

replace_all()
{
    echo "${data//Spark/Flink}"
}

while true
do
    echo " [data=$data]"
    echo
    show_menu
    read -p "Enter choice (1|2|3|4|q|Q):" choice

    case $choice in
        1)
            calculate_length
            ;;
        2)
            remove_spark
            ;;
        3)
            replace_first
            ;;
        4)
            replace_all
            ;;
        q|Q)
            exit
            ;;
        *)
            echo "Invalid input. Use 1|2|3|4|q|Q"
            ;;
    esac
done

Command Substitution

Syntax

Command substitution captures command output into variables.

Example 1: List All System Users

Extract usernames by cutting the first field from /etc/passwd:

cat /etc/passwd | cut -d ":" -f 1

Using a loop (space, newline, and tab serve as delimiters):

#!/bin/bash
#

counter=1
for username in `cat /etc/passwd | cut -d ":" -f 1`
do
    echo "User #$counter: $username"
    counter=$(($counter + 1))
done

Example 2: Calculate Years

echo "Current year: $(date +%Y)"
echo "Next year: $(( $(date +%Y) + 1))"

Summary: Backticks (`) and $() are equivalent, though $() is recommended for clarity. The $() syntax is slightly less portable but widely supported. Backticks work on all POSIX systems. $(()) performs integer arithmetic, and $ before variable names is optional.

Integer operations:

echo "$((50 + 30))"
echo "$(( (80 + 40) / 12 ))"
num1=100
num2=50
echo "$((num1 + num2))"

Example 3: Day of Year Calculations

echo "Today is day $(date +%j) of the year"
echo "Weeks passed: $(($(date +%j) / 7))"
echo "Days remaining: $((365 - $(date +%j)))"
echo "Weeks remaining: $(((365 - $(date +%j)) / 7))"

Example 4: Process Monitoring

Check if nginx is running, start if not:

#!/bin/bash
#
# Exclude the grep process itself
nginx_count=$(ps -ef|grep nginx|grep -v grep|wc -l)

if [ $nginx_count -eq 0 ]; then
    systemctl sttart nginx
fi

Typed Variables

Shell supports type declarations using declare.

Read-only Variables

readonly_var="immutable value"
declare -r readonly_var
readonly_var="new value"  # This will fail

Integer Variables

By default, variables are treated as strings:

val1=100
val2=$val1+50
echo $val2  # Output: 100+50

Declaring as integer:

declare -i val3
val3=$val1+200
echo $val3  # Output: 300

Arrays

Declaring and initializing:

declare -a fruits
fruits=("apple" "banana" "orange" "grape")

Accessing elements:

echo ${fruits[@]}      # All elements
echo ${fruits[1]}      # Second element
echo ${#fruits[@]}     # Array length
echo ${#fruits[0]}     # Length of first element

Function and Variable Listing

declare -f    # Show all functions with definitions
declare -F    # Show function names only

Common Array Operations

items=("cat" "dog" "bird" "fish")

# Display all element
echo ${items[@]}

# Access specific index
echo ${items[2]}

# Get array length
echo ${#items[@]}

# Get element length
echo ${#items[1]}

# Assign to specific index
items[0]="lion"
items[5]="tiger"  # Appends to end

# Delete elements
unset items[2]     # Remove element
unset items        # Clear entire array

# Slice extraction
${items[@]:1:3}    # Elements from index 1, length 3

# Content replacement
${items[@]/i/XX}   # Replace 'i' with 'XX' in all elements

# Iterate through array
for item in ${items[@]}
do
    echo $item
done

Export Variables

#!/bin/bash
#

echo $myvar  # Empty without declaration

myvar=100
declare -x myvar  # Now accessible in child processes

Using declare -x exports the variable to the environment, making it available to subprocesses.

Tags: Shell bash Variables string processing advanced

Posted on Fri, 08 May 2026 14:00:10 +0000 by netpants