行の先頭に日付と時刻が表示されるようにログファイルを再フォーマットしようとしています。ログは次のようになります。
blah, blah, blah, Friday, Mar 13,2015 16:59:42
yadi, yadi, yada, Friday, Mar 13,2015 16:51:11
私は彼らがこのように見えることを望みます:
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
grep -o -i -e '[a-zA-Z]*, [a-z][a-z][a-z] [0-9]*,[0-9][0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]' ~/log.txt
で適切なgrepパターンを見つけるまでに行ってきました。
これらのパターンの結果を情報文字列の左側に移動するにはどうすればよいですか?ご協力いただきありがとうございます。
次の正規表現でsed
を試してください。
$ sed -i.bak 's_\(.*\),[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
ここでは、sed
のグループ置換メソッドを使用して、目的の出力を取得しました。
\(.*\)
は、blah, blah, blah
が一致するため、その後に,[[:blank:]]
があるため、,
まで一致します。\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)
は、行の残りの部分(最初に配置したい部分)と一致します。次に、\2 \1
を使用して、最初に2番目のグループ、次にスペース、最初のグループの順に配置します。
元のファイルは、file.txt.bak
の代わりに-i
だけを使用したくない場合は、-i.bak
としてバックアップされます。
**目的の出力が得られますが、この場合、Regex/sedを使用することは最適なソリューションではありません。
編集:[Internet disconnected] Friday, Mar 13,2015 15:48:34
のような行がある場合、これを試してください:
$ sed -i.bak 's_\(.*[^,]\),*[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 15:48:34 [Internet disconnected]
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
前の正規表現では、\(.*\),[[:blank:]]
(最初の一致グループの後のコンマと空白)がありましたが、出力に新しい行を含めるために、最初の一致グループ\(.*[^,]\)
を作成しました。コンマで終わっていない場合、,*
、つまり1つ以上のコンマと一致します。したがって、新しいsed
コマンドは、前述のすべてのケースで機能します。
awkを使用すると、はるかに簡単な構文になります
awk -F, '{print $4","$5","$6","$1","$2","$3}' file.txt
正規表現の黄金律は「少ないほど多い」です。データに一致する最も単純な正規表現を常に作成するようにしてください。これにより、読みやすく、理解しやすくなるだけでなく、はるかに堅牢であり、形式を少し変更しても壊れません。だから、あなたの場合、あなたは単にやることができます:
$ sed -r 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2\1/' file
Friday, Mar 13,2015 16:59:42blah, blah, blah,
Friday, Mar 13,2015 16:51:11yadi, yadi, yada,
これは、行の先頭からコンマとスペース((.*),
)までのすべてに一致し、パターンが括弧で囲まれているため、\1
として保存します。これで、2番目にキャプチャされたグループ(カッコ内の2番目のパターン)が行の終わりに達するため($
が意味するものです)、最初のグループの正しい部分に一致していることがわかります。
2番目は、1つ以上の非コンマ文字([^,]+
)、コンマ、非コンマの別のセット、別のコンマ、そして行の終わりまで可能な限り多くの非コンマ文字のストレッチを探します。 。そうすれば、最後のフィールドを日付として正しく識別することができます。 s///
は、ここで1番目と2番目のキャプチャパターンの順序を単純に切り替える置換演算子です。
awk
でも同じことができます。おそらく、日付の前のテキストは可変なので、各行に同じ数のフィールドを想定することはできません。したがって、フィールドを行末から逆方向にカウントする必要があります。
$ awk -F, '{
printf "%s,%s,%s, ", $(NF-2),$(NF-1),$NF;
for(i=1;i<NF-3;i++){printf "%s,", $i} print $(NF-3)
}' file
Friday, Mar 13,2015 16:59:42, blah, blah, blah
Friday, Mar 13,2015 16:51:11, yadi, yadi, yada
またはPerlの場合:
$ Perl -lpe 's/(.*), ([^,]+,[^,]+,[^,]*$)/\2, \1/' file
Friday, Mar 13,2015 16:59:42, blah, blah, blah
Friday, Mar 13,2015 16:51:11, yadi, yadi, yada
$ Perl -F, -lane 'print join ",",@F[$#F-2,$#F-1,$#F,0..$#F-3]' file
Friday, Mar 13,2015 16:59:42,blah, blah, blah
Friday, Mar 13,2015 16:51:11,yadi, yadi, yada