从文件中提取子字符串并将它们存储在 shell 个变量中

Extract substrings from a file and store them in shell variables

我正在写剧本。我有一个名为 test.txt 的文件,其内容如下:

a. parent = 192.168.1.2
b. child1 = 192.168.1.21
c. child2 = 192.154.1.2

我需要将值存储在名为 parent、child1 和 child2 的三个不同变量中,如下所示,然后我的脚本将使用这些值:

parent = 192.168.1.2
child1= 192.168.1.21
child2= 192.154.1.2

我如何使用 sed 或 awk 做到这一点?我知道有一种方法可以使用 awk 函数 substr 提取子字符串,但我的特殊要求是如上所述将它们存储在变量中。谢谢

是解决手头特定问题的方法 - 优雅简洁。


更新:Ed 从那以后更新了他的答案以提供正确处理变量值 带有嵌入空格 的解决方案 -原来缺少这提示这个答案。

他的解决方案优于这个 - 更简洁、更高效(唯一需要注意的是,之后您可能必须恢复以前的 $IFS 值)。

如果您需要一个一个地处理变量定义,例如为了根据其他 shell 函数转换变量值,此解决方案可能仍然很有趣或变量之前分配它们。


下面使用bash在一个简化的问题上使用过程替换来一一处理变量定义:

#!/usr/bin/env bash

while read -r name val; do # read a name-value pair

    # Assign the value after applying a transformation to it; e.g.:
    # 'value of' -> 'value:'
    declare $name="${val/ of /: }" # `declare "$name=${val/ of /: }"` would work too.

done < <(awk -F= '{print , }' <<<$'v1=value of v1\nv2=  value of v2')

echo "v1=[$v1], v2=[$v2]" # -> 'v1=[value: v1], v2=[value: v2]'
  • awk 的输出行被逐行读取,拆分为名称和值,并分别声明为 shell 个变量。
  • 因为 read,其中 trim 由空格,只给出了 2 变量名来读入,第二个接收来自第二个的所有内容token _through the end of the line,从而保留内部空白(并且,如所写,将 trim leading and trailing whitespace in the process)。
  • 请注意 declare 通常 而不是 需要在赋值(值)的 RHS 上使用双引号引起来的变量引用(例如 a=$b; 虽然它永远不会伤害)。然而,在这种特殊情况下 - 似乎是因为 LHS(名称)也是一个变量引用 - 需要双引号。

如果您使用 bash 试试这个:

$ declare $(awk '{print "="}' file)
$ echo "$parent"
192.168.1.2

如果文件中的值中包含白色 space 您想要初始化变量的值,那么您只需在调用声明之前将 IFS 设置为换行符,例如(简化了输入文件以突出=标志右侧白色space的重要部分):

$ cat file
parent=192.168.1.2 is first
child1=192.168.1.21 comes after it
child2=and then theres 192.154.1.2

$ IFS=$'\n'; declare $(awk -F'=' '{print "="}' file)
$ echo "$parent"
192.168.1.2 is first
$ echo "$child1"
192.168.1.21 comes after it

我也终于搞定了。谢谢大家的帮助。

counter=0
while read line
do
        declare $(echo $line | awk '{print "="}')
        #echo "$parent"
        if [ $counter = 0 ]
        then
                parent=$(echo $parent)
        fi
        if [ $counter = 1 ]
        then
                child1=$(echo $child)
        else
                child2=$(echo $child)
        fi
        counter=$((counter+1))
done < "/etc/cluster_info.txt"
eval "$( sed 's/..//;s/  *//g' YourFile )"

只是一个相当于 Ed 解决方案的 sed,并且使用 eval 而不是 declare。