2

I have the following in a log file:

[2.09 10:23:56] 
[23.09 10:3:56] 
[23.09 10:23:56] Some other thing
[23.09 10:23:56] 
[23.09 10:23:56] 
[23.09 10:23:5] 
[23.09 10:23:56] Something
[23.09 10:23:56] 

and would like to remove the "empty" lines (the ones only containing the timestamps) using sed. I've tried the following:

sed -i '/\[\d{1,2}\.\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}\] ($|\R)/d' file
sed -i '/\[[0-9][0-9]?\.[0-9][0-9]? [0-9][0-9]?:[0-9][0-9]?:[0-9][0-9]?\] \n/d' file
sed -i '/\[[0-9][0-9]?\.[0-9][0-9]? [0-9][0-9]?:[0-9][0-9]?:[0-9][0-9]?\] ($|\R)/d' file

but nothing seems to do the trick.

Any help is appreciated!

10

As far as I can see, there is no need to create an expression that matches the date string within the brackets at the start of the line.

$ grep -v -x '\[[^]]*\][[:blank:]]*' file
[23.09 10:23:56] Some other thing
[23.09 10:23:56] Something

The above removes lines that start with a bracketed string ([like this]) and only contain optional trailing blanks.

With sed, this would look like

$ sed '/^\[[^]]*\][[:blank:]]*$/ d' file
[23.09 10:23:56] Some other thing
[23.09 10:23:56] Something

The initial bit of the expression, \[[^]]*\] is a literal [ followed by zero or more non-] characters, followed by a literal ].

Using awk, we may set the field separator to ][[:blank:]]*, meaning the ] at the end of the timestamp (and any blanks afterward) would be a delimiter between two fields. If the second field is empty, we don't print the current line.

$ awk -F '][[:blank:]]*' '$2 != ""' file
[23.09 10:23:56] Some other thing
[23.09 10:23:56] Something

As Quasímodo points out in comments (now deleted), using awk 'NF > 2' file would also work with the example data presented in the question. This approach relies on the fact that awk splits the lines into fields on blanks by default. This variation does not care about the specifics of each line and removes all lines except those with more than two whitespace-delimited fields.

2
  • Thank you for your detailed answer. I went and checked @choroba's though because it only uses sed in the end and allows me to create capture groups on the date/time in the future.
    – MemphiZ
    Oct 8 '21 at 0:06
  • @MemphiZ Capturing the date and time was not part of the question, and if you're using the approach in your question to do that and to filter the lines, I suppose you have to do two expression matches, unless you switch to using s///.
    – they
    Oct 8 '21 at 13:17
6
sed '/^\[[0-9]\{1,2\}\.[0-9]\{1,2\} [0-9]\{1,2\}:[0-9]\{1,2\}:[0-9]\{1,2\}\] $/ d'
  • sed doesn't support \d.
  • quantifiers {...} must be backslashed (unless you use -E)
  • the alternative | must be backslashed (unless you use -E)
  • the optional sign ? must be backslashed (unless you use -E)
2
  • Awesome! Thank you very much, this works like a charm!
    – MemphiZ
    Oct 8 '21 at 0:07
  • Everyone should just get in the habit of writing sed -E instead of sed... Makes life a lot easier.
    – alexis
    Oct 8 '21 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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