【问题标题】:How to check if a string is equal to another string based in a substring in Bash如何检查一个字符串是否等于另一个基于 Bash 中子字符串的字符串
【发布时间】:2022-10-13 23:23:21
【问题描述】:

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

我有一个名为 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


    【解决方案1】:

    以下适用于我的机器。我将数组更改为关联数组,将 -x 选项删除为 grep,并使用 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
    ' "$i" | sed 's:[][\/.^$*+?(){}|]:\&:g')
    
                    #Excape right hand side
                    ipaddr=$(printf '%s
    ' "${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
    

    【讨论】:

    • 感谢@Nathan 提供帮助。
    • 您可能需要转义主机名,以便在 sed 中将它们用作字符串文字;例如example.test 将匹配examplestest。此外,虽然您正确修复了@chiko 代码,但您没有指出应避免在for 循环内使用grepsed
    【解决方案2】:

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

    #!/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
    ' "${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&lt;( commands ) 被调用过程替代.它会创建一个包含commands 输出的文件,您可以将其用作参数。

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

    • ! ($2 in aarr) 表示打印主机名所在的记录不是在翻译数组中。

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

    【讨论】:

    • 感谢@Fravadona 的帮助和时间。
    猜你喜欢
    • 1970-01-01
    • 2013-05-12
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    相关资源
    最近更新 更多