bash - 将文件行中的多个项目存储到数组中,并将每个项目存储在其自己的变量中

bash - store multiple items from a file line into array and store each item in its own variable

我有一个多行格式的文件(反向 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 , , , , , }')
     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=

请问我做错了什么?

您的脚本看起来应该用 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(, rev, /[.]/); split(, fqdn, /[.]/);
    domain=; 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

为什么设置 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

错误是

done <<< "$my_array"

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

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

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

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

甚至是有意义的,如果你真的想把变量 first,... 等作为自己的非数组变量,因为你已经在数组中有了数据,你可以直接访问它们,例如通过 ${my_array[0]} 获取第一个元素。