123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- #! /usr/bin/python
- ########################################################################
- #
- # reorder and reformat a file in columns
- #
- # this utility takes lines from its standard input and reproduces them,
- # partially reordered and reformatted, on its standard output.
- #
- # It has the same effect as a 'sort | column -t', with the exception
- # that empty lines, as well as lines which start with a '#' sign, are
- # not affected, i.e. they keep their position and formatting, and act
- # as separators, i.e. the parts before and after them are each sorted
- # separately (but overall field widths are computed across the whole
- # input).
- #
- # Options:
- # -i:
- # --ignore-case:
- # Do not consider case when sorting.
- # -d:
- # --default:
- # What to chage empty fields to.
- # -s <N>:
- # --split=<N>:
- # Treat only the first N whitespace sequences as separators.
- # line content after the Nth separator will count as only one
- # field even if it contains whitespace.
- # Example : '-s 2' causes input 'a b c d e' to be split into
- # three fields, 'a', 'b', and 'c d e'.
- #
- # boards.cfg requires -ids 6.
- #
- ########################################################################
- import sys, getopt, locale
- # ensure we sort using the C locale.
- locale.setlocale(locale.LC_ALL, 'C')
- # check options
- maxsplit = 0
- ignore_case = 0
- default_field =''
- try:
- opts, args = getopt.getopt(sys.argv[1:], "id:s:",
- ["ignore-case","default","split="])
- except getopt.GetoptError as err:
- print str(err) # will print something like "option -a not recognized"
- sys.exit(2)
- for o, a in opts:
- if o in ("-s", "--split"):
- maxsplit = eval(a)
- elif o in ("-i", "--ignore-case"):
- ignore_case = 1
- elif o in ("-d", "--default"):
- default_field = a
- else:
- assert False, "unhandled option"
- # collect all lines from standard input and, for the ones which must be
- # reformatted and sorted, count their fields and compute each field's
- # maximum size
- input_lines = []
- field_width = []
- for line in sys.stdin:
- # remove final end of line
- input_line = line.strip('\n')
- if (len(input_line)>0) and (input_line[0] != '#'):
- # sortable line: split into fields
- fields = input_line.split(None,maxsplit)
- # if there are new fields, top up field_widths
- for f in range(len(field_width), len(fields)):
- field_width.append(0)
- # compute the maximum witdh of each field
- for f in range(len(fields)):
- field_width[f] = max(field_width[f],len(fields[f]))
- # collect the line for next stage
- input_lines.append(input_line)
- # run through collected input lines, collect the ones which must be
- # reformatted and sorted, and whenever a non-reformattable, non-sortable
- # line is met, sort the collected lines before it and append them to the
- # output lines, then add the non-sortable line too.
- output_lines = []
- sortable_lines = []
- for input_line in input_lines:
- if (len(input_line)>0) and (input_line[0] != '#'):
- # this line should be reformatted and sorted
- input_fields = input_line.split(None,maxsplit)
- output_fields = [];
- # reformat each field to this field's column width
- for f in range(len(input_fields)):
- output_field = input_fields[f];
- output_fields.append(output_field.ljust(field_width[f]))
- # any missing field is set to default if it exists
- if default_field != '':
- for f in range(len(input_fields),len(field_width)):
- output_fields.append(default_field.ljust(field_width[f]))
- # join fields using two spaces, like column -t would
- output_line = ' '.join(output_fields);
- # collect line for later
- sortable_lines.append(output_line)
- else:
- # this line is non-sortable
- # sort collected sortable lines
- if ignore_case!=0:
- sortable_lines.sort(key=lambda x: str.lower(locale.strxfrm(x)))
- else:
- sortable_lines.sort(key=lambda x: locale.strxfrm(x))
- # append sortable lines to the final output
- output_lines.extend(sortable_lines)
- sortable_lines = []
- # append non-sortable line to the final output
- output_lines.append(input_line)
- # maybe we had sortable lines pending, so append them to the final output
- if ignore_case!=0:
- sortable_lines.sort(key=lambda x: str.lower(locale.strxfrm(x)))
- else:
- sortable_lines.sort(key=lambda x: locale.strxfrm(x))
- output_lines.extend(sortable_lines)
- # run through output lines and print them, except rightmost whitespace
- for output_line in output_lines:
- print output_line.rstrip()
|