I have a file with the format

47 2013-05-01 1367406011 2 30 15
47 2013-05-01 1367406388 1 29 14
43 2013-05-01 1367407469 1 26 12
42 2013-05-01 1367407489 1 25 11
42 2013-05-01 1367407810 1 24 11
39 2013-05-01 1367409056 1 22 9
41 2013-05-01 1367409610 1 22 9
36 2013-05-01 1367411409 1 22 9
34 2013-05-01 1367412388 1 20 9
32 2013-05-01 1367413208 1 19 9

Where the third column is the time the measurement was taken in seconds since epoch. I'd like to be able to see the time as more every day clock time, and I'm looking for the simplest way to have every column in the file converted.

What's the most effective way of performing the conversion? (I'm on OSX)

  • What OS are you using? – Tanner Faulkner May 1 '13 at 14:23
  • Hi @tanner- I'm on OSX will edit... – Joe May 1 '13 at 20:33
up vote 2 down vote accepted

If you have Perl installed on the machine where you're doing this, and if every line in the file is formatted identically to the example in your question, then the following command line will emit a version of the file with Unix times replaced by human-readable values:

cat source-file | perl -pe's@(^\d+ [\d-]+ )(\d+)@$1 . scalar(localtime($2))@e;'

I'm an Emacs user myself, but I gather from the vim manual that you could apply this command to the contents of your current buffer by doing:

1,$!perl -pe's@(^\d+ [\d-]+ )(\d+)@$1 . scalar(localtime($2))@e;'

In Vim, this quick macro does the job:

qq                           " start recording
0                            " go to first column
2W                           " go to time column
"mciw                        " put time in register m and replace it…
<C-r>=strftime("%T", @m)<CR> " …with localized time
<Esc>                        " exit insert mode
q                            " stop recording

Once the macro is recorded, select all the lines you want to translate then do:

:'<,'>norm @q

If those lines are interleaved with other lines you don't want to touch, you can use the :g[lobal] command to execute the macro only on lines that match some pattern:

:g/2013-05/norm @q

Reference:

:h :normal
:h :global

and

:h strftime()

for date formatting ideas.

With that macro, your sample instantly becomes:

47 2013-05-01 13:00:11 2 30 15
47 2013-05-01 13:06:28 1 29 14
43 2013-05-01 13:24:29 1 26 12
42 2013-05-01 13:24:49 1 25 11
42 2013-05-01 13:30:10 1 24 11
39 2013-05-01 13:50:56 1 22 9
41 2013-05-01 14:00:10 1 22 9
36 2013-05-01 14:30:09 1 22 9
34 2013-05-01 14:46:28 1 20 9
32 2013-05-01 15:00:08 1 19 9
  • +1 for completeness of answer (and teaching me a bit more about vim) but accepted other answer as slightly more repeatable for me... – Joe May 1 '13 at 20:35
  • Good Lord, that macro -- and people say Emacs is overly complex... – Aaron Miller May 1 '13 at 21:09
  • Just like everything in Vim, this macro builds upon small "bricks" that every Vimmer knows: operators, named registers, text-objects. One positive effect is that you don't need to learn this thing as a whole but are able to repeat it and adapt it later without much effort. Or, just like I did, improvise it on the spot without even needing to use your editor. Being totally perl-ignorant, your answer is the one that looks overly complex and verbose to me. But to each his/her own, I guess. – romainl May 2 '13 at 7:30

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.