Home > Software design >  How to check if a string is equal to another string based in a substring in Bash
How to check if a string is equal to another string based in a substring in Bash

Time:03-23

I'm trying to do the following:

I have this file called testing.txt that I want to update each time the ip address or addresses change based on the name (test1ip, test2ip):

127.0.0.1 localhost
somotherrandomip testing
192.168.0.36 test1ip
192.168.0.37 test2ip

This is what I've tried.

#!/bin/bash
array=(
        "192.168.0.34 test1ip"
        "192.168.0.35 test2ip"
)

for i in "${array[@]}"; do
        if ! grep -Fxq "$i" testing.txt
        then
                echo "ip-name=$i is not present, so adding it in testing.txt file" 
                echo "$i" >> testing.txt
        else
                echo "ip-name=$i is present in file, so nothing to do"
        fi
done

However, this script appends a completely new line if the line is not found. What I would like to achieve is to overwrite the line if test1ip or test2ip is found but the ip address change.

Expected result:

127.0.0.1 localhost
somotherrandomip testing
192.168.0.34 test1ip
192.168.0.35 test2ip

I've also read this How to check if a string contains a substring in Bash but it seems i can't figure it out.

Any help is greatly appreciated!

CodePudding user response:

The following works on my machine. I changed the array to an associative array, removed the -x option to grep, and used sed to edit the file in place.

#!/bin/bash

#associative array
declare -A array=(
        [test1ip]="192.168.0.34"
        [test2ip]="192.168.0.35"
)

#Loop over keys of the array
#See parameter expansion in bash manpage
for i in "${!array[@]}"; do
        if ! grep -Fq "$i" testing.txt
        then
                echo "ip-name=$i is not present, so adding it in testing.txt file" 
                echo "${array[$i]} $i" >> testing.txt
        else
                echo "ip-name=$i is present in file so running sed"

                #Replace old IP vith new IP
                sed -Ei "s/[0-9] (\.[0-9] ){3}  $i/${array[$i]} $i/" testing.txt
        fi
done

CodePudding user response:

Here's a bash awk solution that'll do the job efficiently:

#!/bin/bash

array=(
    "192.168.0.34 test1ip"
    "192.168.0.35 test2ip"
    "192.168.0.33 test3ip"
)

awk '
    FNR == NR {
        aarr[$2] = $1
        next
    }
    ! ($2 in aarr)
    END {
        for (host in aarr)
            print aarr[host], host
    }
' <(printf '%s\n' "${array[@]}") testing.txt
127.0.0.1 localhost
somotherrandomip testing
192.168.0.33 test3ip
192.168.0.34 test1ip
192.168.0.35 test2ip

notes:

  • bash's <( commands ) is called process-subtitution. It creates a file containing the output of commands that you can use as argument.

  • awk's FNR == NR is a condition for selecting the first file argument. In this block I create an associative array that translates a hostname to its new IP address.

  • ! ($2 in aarr) means to print the records for which the hostname is not in the translation array.

  • The END is for printing the translation array (new IPs of hostnames).

  • Related