Okay, I may make up of a name.

I use VimNote for note taking task and also have F4 bound with timestamp insertion. So there are some timestamps across all over my notes. They could look like:

In Note A:
  Blah blah -- 2012-02-22T19:02:44Z

In Note B:
  ...
  * Feature Foo (2012-02-22T19:03:14Z) [blah blah]
  * Feature Bar - 2012-02-22T19:03:41Z. (Not a good idea 2012-02-22T19:03:56Z)

In Note C:
  something.... at 2012-02-22,... then blah 2012-02-22T19:04:20Z.

etc.

As you can see, they are notes, so there is no strict way to put my timestamps. They can be at anywhere in a line.

Yesterday, I wanted to know what notes I took the day before, but there was no easy way to make a list which is sorted by timestamp since you can’t not be sure where they will appear, therefore you cannot simply use sort to sort.

Suddenly, grepsort came out of nowhere in my mind. I need to grep the timestamp and then sort by the result. Here is a quick example:

REGEX='2012-02-21[^ ]*' ; sed -n "/$REGEX/ {s/.*\($REGEX\).*/\1 &/;p}" * | sort | cut -d ' ' -f 2-

# breakdown
REGEX='2012-02-21[^ ]*'
sed -n "/$REGEX/ {s/.*\($REGEX\).*/\1 &/;p}" *
| sort
| cut -d ' ' -f 2-

$REGEX is the variable with the search pattern, which is used for grepping. Although it’s called grepsort, there is actually no grep being used. Of course, you can use grep, but sed can do it at once, why bother using grep? Why I not name it as sedsort? Because the fundamental is the grepping, not line editing in sed.

We need sed, because in order to use sort, we have to provide a sorting column. But essentially, if possible, which is not in common command-line tools, we only need to sort by the grepped result.

Anyway, as you can see, we use sed to find (grep) the lines with the pattern and prefix the matched result at the first of line as sorting column, then print out the result.

Next, sort does its job. In this case, we sort by timestamp, which is basically text. You can grep any kind of information and use specific sorting option provided by sort, such as file size, human-readable numbers, or month names.

Lastly, the sorting column is cut out, but I think this can be optional.

By the way, there is a benefit for using grep, if you insist, when does multiple. The file name will be prefixed and you can also use -n for the line number.

I also wrote a simple Python version:

#!/usr/bin/env python
# Copyright 2012 Yu-Jie Lin
# MIT License

from __future__ import print_function
import fileinput
import re
import sys

def main():

  pattern = '(%s)' % sys.argv[1]
  files = sys.argv[2:]
  RE = re.compile(pattern)
  for line in sorted(filter(RE.search, fileinput.input(files)),
                     key=lambda line: RE.search(line).group()):
    print(RE.sub('\033[1;31m\\1\033[0m', line), end='')


if __name__ == '__main__':
  main()

I would say the actual code is sorted(\...). It just as simple as that, but I think some Python wizard can make it even more magical.

Often times, I found it’s very easy to work with shell commands, one-liner can easily save the day. If you are using some GUI, I doubt they will have this kind of feature for you to click.

The only thing I don’t like is both of Bash and Python codes use the regular expression twice. Well, unless you write a command or function grepsort in C, this is how it should be processing. If Python sorted can catch certain of exception from key function, so it can drop some item during the sorting, then filter would not be needed.