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

时间:2015-03-05 22:38:22

标签: linux shell awk sed text-parsing

我正在编写一个脚本。我有一个名为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提取子字符串,但我的特殊要求是如上所述将它们存储在变量中。感谢

4 个答案:

答案 0 :(得分:4)

如果您正在使用bash,请尝试此操作:

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

如果文件中包含要用于初始化变量的值的空格,则只需在调用声明之前将IFS设置为换行符,例如: (简化输入文件以突出显示=标志右侧空白区域的重要部分):

$ 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 $1"="$2}' file)
$ echo "$parent"
192.168.1.2 is first
$ echo "$child1"
192.168.1.21 comes after it

答案 1 :(得分:1)

Ed Morton's answer是解决手头特定问题的方法 - 优雅而简洁。


更新: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 $1, $2}' <<<$'v1=value of v1\nv2=  value of v2')

echo "v1=[$v1], v2=[$v2]" # -> 'v1=[value: v1], v2=[value: v2]'
  • awk的输出行逐行读取,拆分为名称和值,并单独声明为shell变量。
  • 由于read由空白修剪,只有 2 变量名称才能读入,第二个从第二个令牌_到行的末尾接收所有内容,从而保留内部空白(并且,如上所述,将在过程中修剪前导和尾随空格。)
  • 请注意,declare通常要求在赋值的RHS上引用变量引用(值)为双引号(例如a=$b;尽管它从不伤害)。然而,在这种特殊情况下 - 似乎因为LHS(名称)也是一个变量引用 - 需要双引号。

答案 2 :(得分:0)

我终于完成了它。谢谢大家的帮助。

counter=0
while read line
do
        declare $(echo $line | awk '{print $2"="$4}')
        #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"

答案 3 :(得分:0)

eval "$( sed 's/..//;s/  *//g' YourFile )"

只是一个等同于Ed解决方案的sed而且是eval而不是声明。