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]}
获取第一个元素。
我有一个多行格式的文件(反向 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]}
获取第一个元素。