Awk 追加到数组以进行进一步处理
Awk to append out to array for further processing
希望在我目前的 bash 技能无法计算的事情上动脑筋;)
正在解析一个 named.conf 文件以引用实际区域文件的文件名,我想将其复制到一个目录以用于迁移目的。第一步,我想到将区域文件的路径作为 awk 操作的一部分放入一个数组中。从最初的解析循环中出来,然后我可以遍历数组查找新的引用(到下面的 .db 文件)并复制文件。最终,作为区域文件副本的一部分,我希望通过引用域名来重命名目标文件(例如 domaina.com)。
所以,我创建了一个包含域的输入文件,例如:
cat domains.txt
domaina.com
domainb.com
domainc.com
named.conf.deployed 将包含每个相关域的一部分(如下所示)。
// zone: domaina.com [slave]
include "/etc/active/1704500.conf";
现在,回到我到目前为止所取得的成就 - 这并不多 :( 如您所知,该脚本仅设法解析文件并打印 [=39= 中包含的区域的路径] 文件。
while read p; do
grep -A2 "$p" /jail/named/etc/named.conf.deployed | grep include | awk -F\" '{print $(NF-1)}'
done <domains.txt
以上脚本的输出为:
/etc/active/1704500.conf
我可以通过展开 awk 语句来追加到数组中,而不是打印结果吗?或者正如@David 建议我们输出的 tmp 文件。下一步将是打开文件(例如 /etc/active/1704500.conf)并进行类似的解析,因为我真正想要的文件被埋在 .conf 文件中(请参阅下面的内容 1704500.conf)。
// zone: domaina.com
zone "domaina.com"
{
type slave;
file "4725680.db";
};
最后,复制(在上面的示例中)4725680.db 文件并将其重命名为 domaina.com。这就是我希望在下一个循环或代码块中完成的目标。
干杯,
弗雷德里克
请原谅我所有的编辑,这是新手,需要学习(快速)如何解释和传递有关我的挑战的足够信息。
我觉得你的问题很难理解,但我认为这就是你的意思:
arr=() # empty array
arr+=('foo') # add new element
arr+=('bar') # add new element
echo ${arr[@]} # print what we've got
foo bar
# add new elements from awk command
arr+=($(awk -F: 'NR>10 && NR<14 {print }' /etc/passwd))
# see what we have now
echo ${arr[@]}
foo bar nobody root daemon
你在 grepping 而 awking?耻辱,耻辱...
您可以删除链,并使用 awk 查找您正在使用 grep 执行的行:
$ grep "foo" | awk '{print }'
$ awk '/foo/ {print }'
做同样的事情。 awk 可以像 grep 一样 grep 输出行。
你的解释和例子离你想做的有点短。我认为您想保留 etc/active/1704500.conf
并将其与 domaina.com
相关联。也就是说,您需要一个 关联数组 。对吗?
尽管许多人将 awk
视为 cut
的另一个版本,但它本身确实是一种编程语言。 Awk 假设有一个循环,您将程序放入该循环中。 awk 还有一个 BEGIN
和 END
子句来进行预循环和 post 循环处理。
您可能想要做的,不是在 Awk 中创建数组,而是让您的 awk
程序打印出您想要的两个字段,然后您可以在另一个循环中处理它们:
while read p
do
awk '.......' >> awk.temp.$$
done
while read domain file
do
....
done < awk.temp.$$
rm awk.temp.$$
awk
程序看起来像这样:
awk '
/\/\/ zone:/ {
machine =
getline
file = substr( , 2, length () - 3 )
print machine " " file
}' test.txt
/\/\/ zone:/
正在查找该正则表达式。我将该字符串的第三个字段保存到变量 machine
。 getline
让我进入下一行。然后我使用 substr
和 length
来获取第二个单词(这是用引号括起来的文件名),然后去掉开头的引号和结尾的 quote/semicolon.
Awk 不是 shell 的一部分,因此 Awk 中的变量不会在 awk
程序的上下文之外继续存在。在 Awk 中创建数组没有帮助。
我的系统上只有 Bash 3.2,所以我没有 Bash 4 中的关联数组。但是,也许可以在 Awk 中操作输出以允许您使用它来创建关联数组。
我不是 100% 确定,我无法对此进行测试,但您可以这样做:
awk '
BEGIN { printf "(" }
END { print ")" }
/\/\/ zone:/ {
machine =
getline
file = substr( , 2, length () - 3 )
printf "[" machine "]=" file " "
}' test.txt
awk 会输出如下内容:
([machine]=/etc/file [machine2]=/etc/file2)
然后可用于初始化 shell 关联数组。
在 awk 中做所有事情要简单得多(假设我理解问题)。
$ cat domains.txt
domaina.com
domainb.com
domainc.com
$ cat named.conf.deployed
// zone: domaina.com [slave]
include "/etc/active/1704500.conf";
// zone: domainx.com [slave]
include "/etc/active/XXXX.conf";
// zone: domainc.com [slave]
include "/etc/active/CCCCC.conf";
// zone: domainb.com [slave]
include "/etc/active/BBBB.conf";
$ cat domconf.awk
NR == FNR { domains[]; next }
== "zone:" { flag = ( in domains) }
== "include" && flag { print clean(); flag = 0 }
function clean(s) {
gsub("\";?", "", s)
return s
}
$ awk -f domconf.awk domains.txt named.conf.deployed
/etc/active/1704500.conf
/etc/active/CCCCC.conf
/etc/active/BBBB.conf
NR == FNR { domains[]; next }
NR == FNR
表示我们正在读取第一个文件。将域读入 awk 数组。 next
跳过下面的操作并立即读取下一个域。
== "zone:" { flag = ( in domains) }
(到达此处意味着我们正在读取第二个文件。)如果是 "zone" 评论,请检查域的数组。
== "include" && flag { print clean(); flag = 0 }
如果找到域,打印包含名称(删除引号)并重置标志。
编辑
在输出中包含域名:
$ cat domconf.awk
NR == FNR { domains[]; next }
== "zone:" { prev_domain = ; flag = ( in domains) }
== "include" && flag { print prev_domain, clean(); flag = 0 }
function clean(s) {
gsub("\";?", "", s)
return s
}
$ awk -f domconf.awk domains.txt named.conf.deployed
domaina.com /etc/active/1704500.conf
domainc.com /etc/active/CCCCC.conf
domainb.com /etc/active/BBBB.conf
希望在我目前的 bash 技能无法计算的事情上动脑筋;)
正在解析一个 named.conf 文件以引用实际区域文件的文件名,我想将其复制到一个目录以用于迁移目的。第一步,我想到将区域文件的路径作为 awk 操作的一部分放入一个数组中。从最初的解析循环中出来,然后我可以遍历数组查找新的引用(到下面的 .db 文件)并复制文件。最终,作为区域文件副本的一部分,我希望通过引用域名来重命名目标文件(例如 domaina.com)。
所以,我创建了一个包含域的输入文件,例如:
cat domains.txt
domaina.com
domainb.com
domainc.com
named.conf.deployed 将包含每个相关域的一部分(如下所示)。
// zone: domaina.com [slave]
include "/etc/active/1704500.conf";
现在,回到我到目前为止所取得的成就 - 这并不多 :( 如您所知,该脚本仅设法解析文件并打印 [=39= 中包含的区域的路径] 文件。
while read p; do
grep -A2 "$p" /jail/named/etc/named.conf.deployed | grep include | awk -F\" '{print $(NF-1)}'
done <domains.txt
以上脚本的输出为:
/etc/active/1704500.conf
我可以通过展开 awk 语句来追加到数组中,而不是打印结果吗?或者正如@David 建议我们输出的 tmp 文件。下一步将是打开文件(例如 /etc/active/1704500.conf)并进行类似的解析,因为我真正想要的文件被埋在 .conf 文件中(请参阅下面的内容 1704500.conf)。
// zone: domaina.com
zone "domaina.com"
{
type slave;
file "4725680.db";
};
最后,复制(在上面的示例中)4725680.db 文件并将其重命名为 domaina.com。这就是我希望在下一个循环或代码块中完成的目标。
干杯, 弗雷德里克
请原谅我所有的编辑,这是新手,需要学习(快速)如何解释和传递有关我的挑战的足够信息。
我觉得你的问题很难理解,但我认为这就是你的意思:
arr=() # empty array
arr+=('foo') # add new element
arr+=('bar') # add new element
echo ${arr[@]} # print what we've got
foo bar
# add new elements from awk command
arr+=($(awk -F: 'NR>10 && NR<14 {print }' /etc/passwd))
# see what we have now
echo ${arr[@]}
foo bar nobody root daemon
你在 grepping 而 awking?耻辱,耻辱...
您可以删除链,并使用 awk 查找您正在使用 grep 执行的行:
$ grep "foo" | awk '{print }'
$ awk '/foo/ {print }'
做同样的事情。 awk 可以像 grep 一样 grep 输出行。
你的解释和例子离你想做的有点短。我认为您想保留 etc/active/1704500.conf
并将其与 domaina.com
相关联。也就是说,您需要一个 关联数组 。对吗?
尽管许多人将 awk
视为 cut
的另一个版本,但它本身确实是一种编程语言。 Awk 假设有一个循环,您将程序放入该循环中。 awk 还有一个 BEGIN
和 END
子句来进行预循环和 post 循环处理。
您可能想要做的,不是在 Awk 中创建数组,而是让您的 awk
程序打印出您想要的两个字段,然后您可以在另一个循环中处理它们:
while read p
do
awk '.......' >> awk.temp.$$
done
while read domain file
do
....
done < awk.temp.$$
rm awk.temp.$$
awk
程序看起来像这样:
awk '
/\/\/ zone:/ {
machine =
getline
file = substr( , 2, length () - 3 )
print machine " " file
}' test.txt
/\/\/ zone:/
正在查找该正则表达式。我将该字符串的第三个字段保存到变量 machine
。 getline
让我进入下一行。然后我使用 substr
和 length
来获取第二个单词(这是用引号括起来的文件名),然后去掉开头的引号和结尾的 quote/semicolon.
Awk 不是 shell 的一部分,因此 Awk 中的变量不会在 awk
程序的上下文之外继续存在。在 Awk 中创建数组没有帮助。
我的系统上只有 Bash 3.2,所以我没有 Bash 4 中的关联数组。但是,也许可以在 Awk 中操作输出以允许您使用它来创建关联数组。
我不是 100% 确定,我无法对此进行测试,但您可以这样做:
awk '
BEGIN { printf "(" }
END { print ")" }
/\/\/ zone:/ {
machine =
getline
file = substr( , 2, length () - 3 )
printf "[" machine "]=" file " "
}' test.txt
awk 会输出如下内容:
([machine]=/etc/file [machine2]=/etc/file2)
然后可用于初始化 shell 关联数组。
在 awk 中做所有事情要简单得多(假设我理解问题)。
$ cat domains.txt
domaina.com
domainb.com
domainc.com
$ cat named.conf.deployed
// zone: domaina.com [slave]
include "/etc/active/1704500.conf";
// zone: domainx.com [slave]
include "/etc/active/XXXX.conf";
// zone: domainc.com [slave]
include "/etc/active/CCCCC.conf";
// zone: domainb.com [slave]
include "/etc/active/BBBB.conf";
$ cat domconf.awk
NR == FNR { domains[]; next }
== "zone:" { flag = ( in domains) }
== "include" && flag { print clean(); flag = 0 }
function clean(s) {
gsub("\";?", "", s)
return s
}
$ awk -f domconf.awk domains.txt named.conf.deployed
/etc/active/1704500.conf
/etc/active/CCCCC.conf
/etc/active/BBBB.conf
NR == FNR { domains[]; next }
NR == FNR
表示我们正在读取第一个文件。将域读入 awk 数组。 next
跳过下面的操作并立即读取下一个域。
== "zone:" { flag = ( in domains) }
(到达此处意味着我们正在读取第二个文件。)如果是 "zone" 评论,请检查域的数组。
== "include" && flag { print clean(); flag = 0 }
如果找到域,打印包含名称(删除引号)并重置标志。
编辑
在输出中包含域名:
$ cat domconf.awk
NR == FNR { domains[]; next }
== "zone:" { prev_domain = ; flag = ( in domains) }
== "include" && flag { print prev_domain, clean(); flag = 0 }
function clean(s) {
gsub("\";?", "", s)
return s
}
$ awk -f domconf.awk domains.txt named.conf.deployed
domaina.com /etc/active/1704500.conf
domainc.com /etc/active/CCCCC.conf
domainb.com /etc/active/BBBB.conf