正規表現を使ってコマンド行のような文字列を解析してリストに格納する


コマンド行のような文字列を解析してリストに格納する上でのメモ(後半) - 試験運用中なLinux備忘録
正規表現を使って書いてみました。


re.splitだと、後でシングルクオートを追加したりするのが難しそうなので、
re.finditerでも書いてみました。

#encoding:shift-jis
from __future__ import division, with_statement, print_function
import re
from itertools import *

def iparse_cmdline(ss):
    items = re.split(r'([^" \t]*)"([^"]*)"([^" \t]*)', ss)
    for i, x in enumerate(roundrobin(items[0::4], zip(items[1::4], items[2::4], items[3::4]))):
        if i % 2 == 0:
            for item in x.split():
                yield item
        else:
            yield "".join(x)

def parse_cmdline(ss):
    """
    >>> parse_cmdline('aaa      bbb     ccc     "ddd     eee       fff"    ggg  "hhh  iii   "jjj')
    ['aaa', 'bbb', 'ccc', 'ddd     eee       fff', 'ggg', 'hhh  iii   jjj']
    >>> parse_cmdline('aaa    bbb    ccc    "ddd   eee"fff    ggg  "h"hh   iii')
    ['aaa', 'bbb', 'ccc', 'ddd   eeefff', 'ggg', 'hhh', 'iii']
    >>> parse_cmdline('    ls    -l  -a   "a b c.txt"')
    ['ls', '-l', '-a', 'a b c.txt']
    >>> parse_cmdline('    ls    -l  -a   c"d e f.tx"t')
    ['ls', '-l', '-a', 'cd e f.txt']
    """
    
    return list(iparse_cmdline(ss))

def iparse_cmdline2(ss):
    p = 0
    for m in re.finditer(r'([^\s"]*)"([^"]*)"([^\s"]*)', ss):
        for i in ss[p:m.start()].split():
            yield i
        yield m.group(1) + m.group(2) + m.group(3)
        p = m.end()
    for i in ss[p:].split():
        yield i

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

def main():
    import doctest
    doctest.testmod()
    
if __name__ == "__main__":
    main()