reformat.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #! /usr/bin/python
  2. ########################################################################
  3. #
  4. # reorder and reformat a file in columns
  5. #
  6. # this utility takes lines from its standard input and reproduces them,
  7. # partially reordered and reformatted, on its standard output.
  8. #
  9. # It has the same effect as a 'sort | column -t', with the exception
  10. # that empty lines, as well as lines which start with a '#' sign, are
  11. # not affected, i.e. they keep their position and formatting, and act
  12. # as separators, i.e. the parts before and after them are each sorted
  13. # separately (but overall field widths are computed across the whole
  14. # input).
  15. #
  16. # Options:
  17. # -i:
  18. # --ignore-case:
  19. # Do not consider case when sorting.
  20. # -d:
  21. # --default:
  22. # What to chage empty fields to.
  23. # -s <N>:
  24. # --split=<N>:
  25. # Treat only the first N whitespace sequences as separators.
  26. # line content after the Nth separator will count as only one
  27. # field even if it contains whitespace.
  28. # Example : '-s 2' causes input 'a b c d e' to be split into
  29. # three fields, 'a', 'b', and 'c d e'.
  30. #
  31. # boards.cfg requires -ids 6.
  32. #
  33. ########################################################################
  34. import sys, getopt, locale
  35. # ensure we sort using the C locale.
  36. locale.setlocale(locale.LC_ALL, 'C')
  37. # check options
  38. maxsplit = 0
  39. ignore_case = 0
  40. default_field =''
  41. try:
  42. opts, args = getopt.getopt(sys.argv[1:], "id:s:",
  43. ["ignore-case","default","split="])
  44. except getopt.GetoptError as err:
  45. print str(err) # will print something like "option -a not recognized"
  46. sys.exit(2)
  47. for o, a in opts:
  48. if o in ("-s", "--split"):
  49. maxsplit = eval(a)
  50. elif o in ("-i", "--ignore-case"):
  51. ignore_case = 1
  52. elif o in ("-d", "--default"):
  53. default_field = a
  54. else:
  55. assert False, "unhandled option"
  56. # collect all lines from standard input and, for the ones which must be
  57. # reformatted and sorted, count their fields and compute each field's
  58. # maximum size
  59. input_lines = []
  60. field_width = []
  61. for line in sys.stdin:
  62. # remove final end of line
  63. input_line = line.strip('\n')
  64. if (len(input_line)>0) and (input_line[0] != '#'):
  65. # sortable line: split into fields
  66. fields = input_line.split(None,maxsplit)
  67. # if there are new fields, top up field_widths
  68. for f in range(len(field_width), len(fields)):
  69. field_width.append(0)
  70. # compute the maximum witdh of each field
  71. for f in range(len(fields)):
  72. field_width[f] = max(field_width[f],len(fields[f]))
  73. # collect the line for next stage
  74. input_lines.append(input_line)
  75. # run through collected input lines, collect the ones which must be
  76. # reformatted and sorted, and whenever a non-reformattable, non-sortable
  77. # line is met, sort the collected lines before it and append them to the
  78. # output lines, then add the non-sortable line too.
  79. output_lines = []
  80. sortable_lines = []
  81. for input_line in input_lines:
  82. if (len(input_line)>0) and (input_line[0] != '#'):
  83. # this line should be reformatted and sorted
  84. input_fields = input_line.split(None,maxsplit)
  85. output_fields = [];
  86. # reformat each field to this field's column width
  87. for f in range(len(input_fields)):
  88. output_field = input_fields[f];
  89. output_fields.append(output_field.ljust(field_width[f]))
  90. # any missing field is set to default if it exists
  91. if default_field != '':
  92. for f in range(len(input_fields),len(field_width)):
  93. output_fields.append(default_field.ljust(field_width[f]))
  94. # join fields using two spaces, like column -t would
  95. output_line = ' '.join(output_fields);
  96. # collect line for later
  97. sortable_lines.append(output_line)
  98. else:
  99. # this line is non-sortable
  100. # sort collected sortable lines
  101. if ignore_case!=0:
  102. sortable_lines.sort(key=lambda x: str.lower(locale.strxfrm(x)))
  103. else:
  104. sortable_lines.sort(key=lambda x: locale.strxfrm(x))
  105. # append sortable lines to the final output
  106. output_lines.extend(sortable_lines)
  107. sortable_lines = []
  108. # append non-sortable line to the final output
  109. output_lines.append(input_line)
  110. # maybe we had sortable lines pending, so append them to the final output
  111. if ignore_case!=0:
  112. sortable_lines.sort(key=lambda x: str.lower(locale.strxfrm(x)))
  113. else:
  114. sortable_lines.sort(key=lambda x: locale.strxfrm(x))
  115. output_lines.extend(sortable_lines)
  116. # run through output lines and print them, except rightmost whitespace
  117. for output_line in output_lines:
  118. print output_line.rstrip()