シェルスクリプトを使用したテキストファイルの処理とコマンドの生成

シェルスクリプトを使用したテキストファイルの処理とコマンドの生成

次のように、サーバーとドメイン名を含むファイルがあります。

名前.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"

...しかし「参照」シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?」。

関連情報