Printing offset page ranges

Written by

in

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.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.