【问题标题】:bash - store multiple items from a file line into array and store each item in its own variablebash - 将文件行中的多个项目存储到数组中,并将每个项目存储在自己的变量中
【发布时间】:2020-02-03 06:03:20
【问题描述】:

我有一个包含多行格式的文件(反向 dns 条目):

251.2.168.192.in-addr.arpa core.admin.my.lan.

我正在尝试将该行分解为多个变量,以便我可以使用它们来重新创建其 IP 地址,并用作 IPA DNS 入口行

( ipa dnsrecord-add admin.my.lan core --a-rec 192.168.2.251)。

到目前为止,我已经能够想出这个:

while read line ; do 
    IFS=', ' read -r -a my_array <<< $(echo $line | awk -F '[. ]' '{print $4, $3, $2, $1, $7, $8}')
     while IFS= read -r first second third fourth fifth sixth; do 
        echo "first=$first second=$second third=$third fourth=$fourth fifth=$fifth sixth=$sixth"; 
        done <<< "$my_array" 
        unset my_array 
done <reverse_entries.txt

但这只会创建第一个变量$first

first=192 second= third= fourth= fifth= sixth=
first=10 second= third= fourth= fifth= sixth=
first=192 second= third= fourth= fifth= sixth=
first=192 second= third= fourth= fifth= sixth=
first=192 second= third= fourth= fifth= sixth=
first=192 second= third= fourth= fifth= sixth=
first=192 second= third= fourth= fifth= sixth=

请问我做错了什么?

【问题讨论】:

  • 你能从reverse_entries.txt 发布一些实际的示例行吗?您的多个 read 循环肯定是复杂的,不是必要的
  • 我已经编辑了问题以使示例行更加明显。

标签: linux bash centos7 freeipa


【解决方案1】:

为什么你设置IFS=', ' 在示例中我没有看到任何逗号。并使用数组? 根据您的示例,有两个主要部分,第一个 251.2.168.192.in-addr.arpa 和第二个 core.admin.my.lan. 所以我将从这个开始,在这两个部分中分割线,而不是让它们看起来像我需要的那样。

对于这个测试文件

$ cat reverse_entries.txt
251.2.168.192.in-addr.arpa core.admin.my.lan.
251.2.168.193.in-addr.arpa coe.admin.my.lan.
251.2.168.194.in-addr.arpa cor.admin.my.lan.

while read line ; do
    read -r ip name <<< $line
    ip=${ip/.in-addr.arpa/} # remove .in-addr.arpa from ip
    ip=( ${ip//./ } )       # make ip an array
    ip=${ip[3]}.${ip[2]}.${ip[1]}.${ip[0]} # reconstruct ip
    core=${name%%.*}        # get core part from name
    name=${name%.}          # remove last dot from name
    name=${name#*.}         # remove core. from name
    # print result line
    echo "ipa dnsrecord-add $name $core --a-rec $ip"
done < reverse_entries.txt

输出

ipa dnsrecord-add admin.my.lan core --a-rec 251.2.168.192
ipa dnsrecord-add admin.my.lan coe --a-rec 251.2.168.193
ipa dnsrecord-add admin.my.lan cor --a-rec 251.2.168.194

【讨论】:

  • in-addr.arpa 中的八位字节。 PTR 记录被反转。第一个结果应该是 192.168.2.251。
  • @tripleee,没注意到,更新,谢谢。
【解决方案2】:

错误是

done <<< "$my_array"

确实只会传递第一个元素。你想传输整个数组,因此应该写

done <<< "${my_array[@]}"

当然我想知道为什么你需要一个虚拟的 while-loop (内部 while 将只执行一次外部循环的每次迭代),当你可以做一个简单的

read -r first second third fourth fifth sixth <<< "${my_array[@]}"

甚至仅有意义,如果您真的想将变量 first,... 等作为自己的非数组变量,因为由于数组中已经有数据,您可以直接访问它们,例如${my_array[0]} 作为第一个元素。

【讨论】:

    【解决方案3】:

    你的脚本看起来你应该用 awk 重写它;但这里有一个简单的 Bash 脚本,如果你真的想用 Bash 编写它,希望它至少能提供一个关于如何简化脚本的提示。

    #!/bin/bash
    
    split () {
        local IFS='.'
        printf ' %s' $*
    }
    while read ptr fqdn; do
        ips=($(split "$ptr"))
        domain=${fqdn#*.}
        host=${fqdn%.$domain}
        echo "ipa dnsrecord-add ${domain%.} $host --a-rec ${ips[3]}.${ips[2]}.${ips[1]}.${ips[0]}"
    done <<\:
    251.2.168.192.in-addr.arpa core.admin.my.lan.
    :
    

    输出:

    ipa dnsrecord-add admin.my.lan core --a-rec 192.168.2.251
    

    这是一个快速而肮脏的 Awk 重新实现。

    awk '{ split($1, rev, /[.]/); split($2, fqdn, /[.]/);
        domain=$2; sub("^" fqdn[1] "[.]", "", domain); sub(/[.]$/, "", domain);
        print "ipa dnsrecord-add", fqdn[1], domain,\
             "--a-rec", rev[4] "." rev[3] "." rev[2] "." rev[1] }' reverse_entries.txt
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多