#/usr/bin/python '''Methods for parsing a Java properties file as described by: http://java.sun.com/j2se/1.4.2/docs/api/java/util/Properties.html ''' import sys backslash = '\\' def parsePropertyLine(s): '''Returns the property string and a boolean indicating whether the property ends with a line-continuation character. If the line does end in a conitinueing \, then that character is NOT returned in the string.''' if not s.endswith(backslash): return s, False ls = len(s) last = ls - 1 for i in range(1, last): if s[last - i] != backslash: if i%2: return s[:-1], True return s, False if last % 2: return s[:-1], True return s, False _escapeToWriteDict = { '\n' : '\\n', '\r' : '\\r', '\t' : '\\t', ' ' : '\\ ', backslash : backslash + backslash } _readingEscapeDict = { 'n' : '\n', 't' : '\t', 'r' : '\r', } def parsePropString(s): keyList = [] valList = [] escape = False separatorSeen = False charIterator = iter(s) for c in charIterator: if escape: keyList.append(_readingEscapeDict.get(c,c)) escape = False elif c == backslash: escape = True else: if c in [':', '=']: separatorSeen = True break elif c.isspace(): break keyList.append(c) for c in charIterator: if (not separatorSeen) and (c in [':', '=']): separatorSeen = True else: if not c.isspace(): valList.append(c) break for c in charIterator: if escape: valList.append(_readingEscapeDict.get(c,c)) escape = False elif c == backslash: escape = True else: valList.append(c) value = ''.join(valList) return ''.join(keyList), value def propertyIterator(fileObj): currComments = [] propStr = '' for linePlus in fileObj: line = linePlus[:-1] lstrLine = line.lstrip() if lstrLine: if lstrLine[0] == '#' or lstrLine[0] == ':': if propStr: key, val = parsePropString(propStr) yield key, val, '\n'.join(currComments) currComments = [line] propStr = '' else: currComments.append(line) else: p, midLine = parsePropertyLine(lstrLine) propStr = propStr + p if not midLine: key, val = parsePropString(propStr) yield key, val, '\n'.join(currComments) currComments = [] propStr = '' else: currComments.append('') if propStr or currComments: if propStr: key, val = parsePropString(propStr) else: key, val = '', '' yield key, val, '\n'.join(currComments) def escape(s): return ''.join([_escapeToWriteDict.get(i, i) for i in s]) if __name__ == '__main__': ind = 1 outputComments = False if len(sys.argv) > 1 and sys.argv[1] == '-c': outputComments = True ind = 2 files = sys.argv[ind:] if not files: files = [None] for file in files: try: if file is not None: f = open(file, 'rU') else: f = sys.stdin except IOError: sys.exit('Could not open %s' % f) for k, v, c in propertyIterator(f): if outputComments: if k: if c: sys.stdout.write('%s\n%s=%s\n' % (c, escape(k), escape(v))) else: sys.stdout.write('%s=%s\n' % (escape(k), escape(v))) else: sys.stdout.write('%s\n' % c) elif k: sys.stdout.write('%s=%s\n' % (escape(k), escape(v)))