2008-04-18

This is getting awk-ward

Ideas from readers DrewP and Justin have greenbar approaching the size of the original awk version. Thank you both.

#!/usr/bin/python -u

import sys

try:
pat = sys.argv[1]
except IndexError:
pat = None

green = True
for line in iter(sys.stdin.readline, ""):
if (pat and pat in line) or (not pat and green):
print "\x1b[7m%s\x1b[0m" % line.rstrip()
else:
print line,
green = not green

5 comments:

fawcett said...

For kicks, I wrote this up using pyline. It doesn't handle the optional pattern, though, so it's not totally equivalent.

Matching a pattern:

pyline "('pattern' in line or num%2) and '\x1b[7m%s\x1b[0m'%line or line"

No matching:

pyline "num % 2 and '\x1b[7m%s\x1b[0m' % line or line"

If you're interested, I'd adapt pyline to accept additional command line parameters, letting a one-liner work more like your example does, and handle an optional pattern case.

RyanDBair said...

Why don't you use itertools?

for line , green in izip( lines , cycle( ( True , False ) ) ):

Chris Lambacher said...

You could use itertools.cycle and itertools.izip to get the correct values for green on each line.


#!/usr/bin/python -u

import sys, itertools as it

try:
  pat = sys.argv[1]
except IndexError:
  pat = None


for green, line in it.izip(it.cycle((True,False)),iter(sys.stdin.readline, ""):
  if (pat and pat in line) or (not pat and green):
    print "\x1b[7m%s\x1b[0m" % line.rstrip()
  else:
    print line,

Chris Lambacher said...

Doh! Ryan squeaked in there while I was trying to get some sort of indenting to work.

Alex said...

You could implify the 4-liner try/except block setting pat to a 1-liner such as:

pat = (sys.argv+[None])[1]

or (in Python 2.5 or better):

pat = sys.argv[1] if len(sys.argv)>1 else None

Also, iter(sys.stdin.readline, "") could be simplified into sys.stdout (in an iteration context, a file object is an iterator on the file's textlines).

Alex