Bash - ファイル構成形式の変更

Bash - ファイル構成形式の変更

私は変更したい:

これ:

client 192.168.100.1 {
    secret = ThisIStheSECRET
    shortname = HOSTNAME
}
client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}

それ:

client HOSTNAME { secret = ThisIStheSECRET, ipaddr = 192.168.100.1 }
client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }

どうすればいいですか?どのツールを使用する必要がありますか?

答え1

簡単なawkスクリプト:

awk '
    /^client/               { ipaddr    = $2                              }
    /^[[:blank:]]*shortname/{ shortname = $3                              }
    /^[[:blank:]]*secret/   { secret    = $0; sub("^[^=]*= ", "", secret) }
    /^}/ {
        printf("client %s { secret = %s, ipaddr = %s }\n",
            shortname, secret, ipaddr);
    }' file

入力ファイルで必要な情報を見つけたら、簡単に解析し、行の先頭でを押すと}収集された情報が正しい形式で出力されます。

テキストの解析は、テキストにsecret次の内容が含まれると予想されるため、特別です。何もない、さらにフィールド区切り記号。最初に変数をsecret完全な行に設定し、最初のスペースの前のすべてのエントリ=とその後の単一のスペースを削除します。

与えられたファイル

client 192.168.100.2 {
    secret = ThisIStheSECRET2
    shortname = HOSTNAME2
}
client 10.0.0.1 {
    secret =     This is it, the secret!, ipaddr = 10.0.0.1
    shortname = myhost.local
}

(パスワードの先頭にスペースが4つあることに注意してください。)これを行うと、次のような結果が得られます。

client HOSTNAME2 { secret = ThisIStheSECRET2, ipaddr = 192.168.100.2 }
client myhost.local { secret =     This is it, the secret!, ipaddr = 10.0.0.1, ipaddr = 10.0.0.1 }

答え2

私は次のことをします:

perl -0777 -pe 's{client\s+(\S+)\s*\{\s*(secret = .*)\s+shortname\s*=\s*(.*)\s*\}}
                 {client $3 { $2, ipaddr = $1 }}g'

答え3

私が望んでいたほど「簡単」ではありませんが、これは問題を解決します。

perl -pe 's/(\w)\s*$/\1,\n/;' your_filename | perl -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;'

英数字(A〜Z、a〜z、0〜9、および_)で終わる行にカンマを追加する正規表現を実行します。

改行}(負のバックビューを活用)で終わらない限り、改行(およびその周辺の空白)を空白に置き換える別の正規表現を実行し、最後に最終書式設定の正規表現を実行します(ホスト名とIPを切り替えます。し、無関係な内容を削除)コンマ)

これは改行を無視し、結果を新しいファイル(または既存のファイル)にリダイレクトして> your_new_filename最後に追加できます。これにより、このソリューションはフラグを使用して-iファイルを変更できます。

perl -i -pe 's/(\w)\s*$/\1,\n/;' your_filename
perl -i -pe 'BEGIN{undef $/;} s/(?<!})\s*\n\s*/ /smg;' -e 's/(client )(\S+)(.*?)(\w+),\s*}/\1\4\3\2 }/g;' your_filename

答え4

この問題を解決するより良い方法があると確信していますが、次の組み合わせで解決しましsedawk

sed ':a;N;$!ba;s/\n/ /g' file | sed -e 's/    //g' -e 's/ client/\nclient/' | awk '{print $1" "$9" "$3" "$4" "$5" "$6",  ipaddress "$8" "$2" "$10}'

説明する

  • sed ':a;N;$!ba;s/\n/ /g'すべての新しい行を空白に置き換えます。これを参照してくださいこの回答より多くの情報を知りたい場合
  • sed -e 's/ //g'4つのスペーサーブロックを1つのスペースに交換します。
  • -e 's/ client/\nclient/'クライアント文字列が一致する場合は、新しい行を追加します。
  • awk '{print $1" "$9" "$3" "$4" "$5" "$6", ipaddress "$8" "$2" "$10}'デフォルトでは、awkはテキストをスペースで区切っているので、ここではホスト名変数($ 9)とIPアドレス変数($ 2)を必要な順序で印刷するだけです。 "shortname"変数($ 7)を無視して、 ",ipaddress"テキストをハードコードできます。

関連情報