使用 shell 脚本处理文本文件并创建命令

使用 shell 脚本处理文本文件并创建命令

我有一个包含服务器和域名的文件,如下所示。

名称.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 循环处理文本被认为是不好的做法?”。

相关内容