centos – How to add an empty line after lines starting with a timestamp

In vim, you could do:

:%s/\v^\d{4}(-\d{2}){2} \d{2}(:\d{2}){2}.*/&\r

Note the \v for very magic so you don’t need to add backslashes before every {}().

Yes, \r in the replacement adds a newline (splits the line in two using the wording at :help s/\r), not a carriage return as one might have expected.

In standard vi (\d, \v, \r, norm being all vim extensions), the equivalent would look like:

:%s/^[[:digit:]]\{4\}\(-[[:digit:]]\{2\}\)\{2\} [[:digit:]]\{2\}\(:[[:digit:]]\{2\}\)\{2\}.*/&^M/

Where the ^M is entered by pressing Ctrl+V followed by Enter (and again inserts a LF aka newline aka ^J, not CR aka carriage-return aka ^M).

But the vi implementation on CentOS is vim (and has been since at least as far back as CentOS 4) so you should be able to rely on the vim extensions in vi there.

In any case tr is a tool to transliterate, replace characters with other characters or delete or squeeze them, it cannot be used here.

sed, awk or perl could be used (AFAIK, \d as a regex operator originated in perl):

perl -pi -e '$_ .= "\n" if /^\d{4}(-\d{2}){2} \d{2}(:\d{2}){2}/' your-file

To edit the file in place. Or:

perl -p -e '$_ .= "\n" if /^\d{4}(-\d{2}){2} \d{2}(:\d{2}){2}/' < your-file > new-file

To get the result into a new file.

Or here, provided the Regex::Common::time module is available:

perl -MRegexp::Common=time -p -e '
  $_ .= "\n" if m{^$RE{time}{strftime}{-pat=>"%Y-%m-%d %H:%M:%S"}}
  ' < your-file > new-file

Which will do a stricter matching (not match on 2023-13-00 25:61:62 for instance). There’s also a $RE{time}{iso} which will match those dates, but also many other variants of ISO8601 dates including some without date or time component, so can’t be used here.

You can see the actual regex with:

$ perl -MRegexp::Common=time -le 'print $RE{time}{strftime}{-pat=>"%Y-%m-%d %H:%M:%S"}'
(?:(?:\d{4})-(?:(?:(?=[01])(?:0[1-9]|1[012])))-(?:(?:(?=[0123])(?:0[1-9]|[12]\d|3[01]))) (?:(?:(?=[012])(?:[01]\d|2[0123]))):(?:(?:[0-5]\d)):(?:(?:(?=[0-6])(?:[0-5]\d|6[01]))))

Read more here: Source link