如何根据 Bash 中的子字符串检查一个字符串是否等于另一个字符串

How to check if a string is equal to another string based in a substring in Bash

我正在尝试执行以下操作:

我有一个名为 testing.txt 的文件,每次 IP 地址或地址根据名称(test1ip、test2ip)更改时我都想更新它:

127.0.0.1 localhost
somotherrandomip testing
192.168.0.36 test1ip
192.168.0.37 test2ip

这是我试过的。

#!/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

但是,如果找不到该行,此脚本会附加一个全新的行。我想要实现的是,如果找到 test1ip 或 test2ip 但 ip 地址发生变化,则覆盖该行。

预期结果:

127.0.0.1 localhost
somotherrandomip testing
192.168.0.34 test1ip
192.168.0.35 test2ip

我也读过这个How to check if a string contains a substring in Bash,但我似乎无法理解。

非常感谢任何帮助!

这里有一个 bash + awk 解决方案,可以有效地完成这项工作:

#!/bin/bash

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

awk '
    FNR == NR {
        aarr[] = 
        next
    }
    ! ( 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

备注:

  • bash<( commands )被称为process-subtitution。它创建一个包含 commands 输出的文件,您可以将其用作参数。

  • awkFNR == NR是选择第一个文件参数的条件。在这个块中,我创建了一个关联数组,将主机名转换为其新的 IP 地址。

  • ! ( in aarr)表示打印翻译数组中hostname为not的记录。

  • END 用于打印翻译数组(主机名的新 IP)。

以下内容适用于我的机器。我将数组更改为关联数组,删除了 grep 的 -x 选项,并使用 sed 就地编辑文件。

#!/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"

                #Escape sed left hand side
                #Adapted for extended regular expressions from https://unix.stackexchange.com/a/129063/309759
                i=$(printf '%s\n' "$i" | sed 's:[][\/.^$*+?(){}|]:\&:g')

                #Excape right hand side
                ipaddr=$(printf '%s\n' "${array[$i]}" | sed 's:[\/&]:\&:g;$!s/$/\/')

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