web-dev-qa-db-ja.com

パターンを行頭に移動

行の先頭に日付と時刻が表示されるようにログファイルを再フォーマットしようとしています。ログは次のようになります。

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パターンを見つけるまでに行ってきました。

これらのパターンの結果を情報文字列の左側に移動するにはどうすればよいですか?ご協力いただきありがとうございます。

5
Tfb9

次の正規表現で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コマンドは、前述のすべてのケースで機能します。

5
heemayl

awkを使用すると、はるかに簡単な構文になります

awk -F, '{print $4","$5","$6","$1","$2","$3}' file.txt
4
Panther

正規表現の黄金律は「少ないほど多い」です。データに一致する最も単純な正規表現を常に作成するようにしてください。これにより、読みやすく、理解しやすくなるだけでなく、はるかに堅牢であり、形式を少し変更しても壊れません。だから、あなたの場合、あなたは単にやることができます:

$ 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
3
terdon