I was printing a document the other day that contained some colour pages. Being a cheapskate, I printed the whole document to the black-and-white laser printer down the hall, then printed the colour pages on the more expensive colour printer.
Unfortunately, I had just written down the ranges of the pages to print using the page numbers on the document, but I had forgotten that the page number had started again from page 12 in the actual document. This meant I had printed all the ranges 12 pages shifted on the colour document. It wasn’t a complete loss, as some of the pages overlapped. How to print only the pages which hadn’t been printed already? Unix shell to the rescue!
I came up with the following one-liner which saved me literally minutes of menial counting:
echo {46..50} {52..56} {59..68} 70
| tr " " "n"
| awk '{printed[$1+12]++; printed[$i]--} END {for (i in printed) if (printed[i]==1) print i}'
| sort | tr "n" ","
This yields a nice comma separated list of pages that I can print:
58,71,72,73,74,75,76,77,78,79,80,82
I had also previously written a range parsing class in Python, which looks like this:
class Range(object):
""" class containing the idea of non-contiguous ranges """
def __init__(self, s):
""" Parse range from string """
self.string = s
self.items = []
for group in s.split(','): # 1-2,5-7,9
if '-' in group:
[start, stop] = [int(e) for e in group.split('-')]
else:
start = int(group)
stop = start
items = range(start, stop+1)
self.items = self.items + items
def __iter__(self):
return iter(self.items)
def __str__(self):
return self.string
def __repr__(self):
return "Range('" + str(self) + "')"
With that defined, I could also solve the problem like this in a python console:
wantedtoprint = set(Range('46-50,52-56,59-68,70').items)
printed = set(i+12 for i in wantedtoprint)
sorted(printed.difference(wantedtoprint))
=> [58, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 82]
This is why I always have a terminal open.