私は変更したい:
これ:
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
この問題を解決するより良い方法があると確信していますが、次の組み合わせで解決しましsed
たawk
。
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"テキストをハードコードできます。