Best way to increment numbers in one line in Linux

1

1

I have one line with lot of entries among which is also time.

 ('DEFAULT',17,NULL,'2014-07-14 10:30:00','Something','2014-07-14 06:30:00',1),('DEFAULT',26,NULL,'2014-07-14 12:00:00','Something2,'2014-07-14 11:00:00',1),...

I would like to increment each time by few hours. in 24 h format. For example 10:30:00 would become 15:30:00.

What is the best universal tool for this job? I am thinking in terms of:

  1. system utilities like awk, sed ..& whatever else I do not know

  2. vim

  3. scripting languages like bash or python`

What would be the canonical way to do it?

ps-aux

Posted 2015-05-23T00:15:31.513

Reputation: 3 397

Question was closed 2015-05-29T21:25:46.747

Whatever you are comfortable with :) I for example would use perl beucase I'm familiar with it and has really powerfull regexp – Dan – 2015-05-23T07:05:27.950

Answers

0

Just to clarify:

vim is a system utility (a text editor) on most *nix systems. awk, sed, and bash are languages (or tools, depending on the context) that you can use to parse and alter text.

What do you need to increment the time for, and how often will you need to increment it? Those factor into what tools you'll want to use. In any case, this is a multi-part effort, ASSUMING THIS IS NOT SQL:

  1. You're first matching partial strings within a string. You can use awk, sed, or grep -e, with a regex, to pull those substrings out.

  2. When you have those values, you'll convert them to integers (or if you're using a fuller language like python, you might be able to cast them into datetime values using a library). You'll have to do the math you need (and validation, if applicable) to alter those values.

  3. Finally, you'll add the replaced values into the line and save the altered file.

Honestly, though, this looks like sql, so it might be much easier to use the built-in tools in that language to alter those values.

cognoscente

Posted 2015-05-23T00:15:31.513

Reputation: 56

1You say that awk and sed are in a whole different category from vim?  Are you quoting some reference, or is this just your opinion?  Either way, I disagree; I believe that you’re pointing out a distinction that doesn’t exist.  awk and sed are utility programs; so is vim.  awk and sed have command languages; do does vim (and also bash; and, while shells are not normally considered utility programs, they certainly are programs).  awk and sed are programs that you can use to <strike>parse</strike> analyze and alter text; so is vim. – G-Man Says 'Reinstate Monica' – 2015-05-23T05:38:35.773

I'm quoting years in the industry using the tools. vim is a language the same way Microsoft Word is a language. I'm not interested in arguing semantics with you. I only clarified because the language OP used to describe them suggested an unfamiliarity, and I was trying to help define the terms for them. – cognoscente – 2015-05-24T19:15:35.890

0

There are some good hints in this answer suggesting a path of least resistance using a scripting language like Perl, Python, Ruby, etc. which allows intermixing of mathematical and matching operations.

Here is a quick hack with Perl:

$ echo '2014-12-05 10:00:10, 1234, 2015-02-01 09:12:24' | perl -pe \
    's/(\d{4}-\d{2}-\d{2} )(\d{2})(:\d{2}:\d{2})/join("",$1,$2+3,$3)/eg'
2014-12-05 13:00:10, 1234, 2015-02-01 12:12:24
$

In this simplistic example the digit character class (\d) followed by the repetition indicator (e.g. {2}) is used to capture positional components of the date and we blindly do arithmetic on the hour field. This type of solution is only appropriate when you know your data well enough to ensure that simplistic arithmetic on the hours field will not cause the day to roll over.

Revisiting this problem to address correct date/time arithmetic when the hours field overflows as prompted by @Lieven, the Perl core module Time::Piece (Perl>5.8) can be used:

$ echo '2014-12-05 22:00:00, 1234, 2015-02-01 09:12:24' | \
    perl -MTime::Piece -pe \
        's/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/( \
            Time::Piece->strptime($1, "%Y-%m-%d %T") \
            + (60*60*3))->strftime("%Y-%m-%d %T")/eg'
2014-12-06 01:00:00, 1234, 2015-02-01 12:12:24
$

This example input has been updated to show graceful handling of hours values rolling over into the next day. It pulls in the Time::Piece module at the command-line, matches off the date-time from the input, converts to Time::Piece objects in order to perform date/time arithmetic, then stringify back into the desired output format.

deaks

Posted 2015-05-23T00:15:31.513

Reputation: 21

One might get 99% right using regex but there's no easy way to account for having to increment the day, month or year (and that's not even touching leap years). – Lieven Keersmaekers – 2015-05-25T09:47:57.497

@Lieven_Keersmaekers: constructing date time objects from the match results in order to do this math properly seems reasonable but my first instinct with Perl would be to make a script using box notation and more verbose style to make the intent clearer. As a one liner I figure the best bet is to know your data and determine what transformations will give the desired result. – deaks – 2015-05-25T15:17:10.493