我有一个包含服务器和域名的文件,如下所示。
名称.txt:
ABCDomain ContractABCServer_1
ABCDomain ABC_server1
LinkDomain CoreLinkServer_1
TADDomain TADServer_1
(我在对其他文件执行排序和唯一操作后得到上述文件。)---只是附加信息
我需要从上面的文件中提取值并将其作为以下格式的参数传递给 xyz 命令(该命令用于重新启动服务器)。
输出:
"ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
我正在使用下面所述的逻辑,但它没有给我所需的输出,因为每个集合的域名必须只出现一次。我也很难保持同一条线。
- - - - - -开始 - - -
DOMAIN=''
IFS=' '
while read line
do
DOMAIN=$(echo "$line" | awk -F " " '{print $1}')
for word in $line
do
if [[ "$word" == "$DOMAIN" ]]; then
Server=$(echo "$line" | awk -F " " '{print $2}' )
echo -n "(server:$ServerName"
fi
done
done < Names.txt
答案1
{
if (dom[$1])
dom[$1]=dom[$1]","$2
else
dom[$1]=$2
}
END {
ORS=",";
for (d in dom)
if (d)
print ("\""d"(server:"dom[d]")""\"")
}
这是快速但肮脏的 awk 解决方案。将其保存为 Something.awk,然后运行:
awk -f something.awk Names.txt
快速修复回复您的问题评论:
{ dom[$1]=dom[$1] ? dom[$1]",server:"$2 : "server:"$2 }
END {
for (d in dom)
if (d) {
out && out = out","
out = out"\""d"("dom[d]")""\""
}
print out
}
答案2
您可以直接组合以逗号分隔的字符串awk
并在末尾打印组合:
$1 == "ABCDomain" {d = (d == "") ? $2 : d "," $2; next}
$1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next}
$1 == "TADDomain" {t = (t == "") ? $2 : t "," $2; next}
END {
printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
}
前任。
$ awk '
$1 == "ABCDomain" {d = (d == "") ? $2 : d "," $2; next}
$1 == "LinkDomain" {l = (l == "") ? $2 : l "," $2; next}
$1 == "TADDomain" {t = (t == "") ? $2 : t "," $2; next}
END {
printf("\"ABCDomain(server:%s)\",\"LinkDomain(server:%s)\",\"TADDomain(%s)\"\n", d, l, t)
}' Names.txt
"ABCDomain(server:ContractABCServer_1,ABC_server1)","LinkDomain(server:CoreLinkServer_1)","TADDomain(TADServer_1)"
答案3
您可以使用此代码,请在执行之前阅读代码,因为它会在/tmp
名为 的文件夹中创建一个目录domains
,然后将其删除
DOMAIN=''
IFS=' '
declare -A domain
mkdir /tmp/domains
while read line
do
DOMAIN=$(echo $line | awk '{print $1}')
SERVER=$(echo $line | awk '{print $2}' )
echo "$SERVER," >> /tmp/domains/$DOMAIN
domain[$DOMAIN]=1
done < Names.txt
sed -ir "$ s/.,$//" /tmp/domains/*
for i in "${!domain[@]}"; do
echo -n "$i(server:";
while read line ; do
echo -n "$line" ;
done < /tmp/domains/$i
echo ")"
done
rm -rf /tmp/domains
这将在 /tmp 文件夹中创建一个包含以下数据的文件夹,以便每个域文件名都包含其中包含的服务器列表
$ ls -lhtr /tmp/domains/
total 12K
-rw-rw-r-- 1 arushirai arushirai 11 Jun 19 17:54 TADDomain
-rw-rw-r-- 1 arushirai arushirai 16 Jun 19 17:54 LinkDomain
-rw-rw-r-- 1 arushirai arushirai 32 Jun 19 17:54 ABCDomain
$ cat /tmp/domains/ABCDomain
ContractABCServer_1,
ABC_server
$ cat /tmp/domains/LinkDomain
CoreLinkServer_
$ cat /tmp/domains/TADDomain
TADServer_
答案4
(更新以更正输出格式)
使用awk
:
BEGIN { OFS = "," }
{ servers[$1] = (servers[$1] == "" ? "server:" $2 : servers[$1] "," "server:" $2 ) }
END {
$0 = ""
for (domain in servers)
$(++n) = sprintf("\"%s(%s)\"", domain, servers[domain])
print
}
这将在解析输入文件时将服务器作为逗号分隔的字符串添加到主块中的特定域。这是通过修改servers
保存特定域的服务器的数组来完成的(域是数组中的键)。
在该END
块中,我们循环遍历数组中的所有键/域servers
并以指定格式创建输出记录。
在提供的数据上运行:
$ awk -f script.awk names.txt
"TADDomain(server:TADServer_1)","ABCDomain(server:ContractABCServer_1,server:ABC_server1)","LinkDomain(server:CoreLinkServer_1)"
一个基本等效的bash
脚本(bash
关联数组需要 4.3+):
declare -A servers
while read domain server; do
servers[$domain]+="${servers[$domain]:+,}server:$server"
done <names.txt
for domain in "${!servers[@]}"; do
out+="${out:+,}\"$domain(${servers[$domain]})\""
done
printf '%s\n' "$out"
...但请参阅“为什么使用 shell 循环处理文本被认为是不好的做法?”。