#!/usr/bin/env python # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import re def quote(input_str, specials, escape='\\'): """Returns a quoted version of |str|, where every character in the iterable |specials| (usually a set or a string) and the escape character |escape| is replaced by the original character preceded by the escape character.""" assert len(escape) == 1 # Since escape is used in replacement pattern context, so we need to # ensure that it stays a simple literal and cannot affect the \1 # that will follow it. if escape == '\\': escape = '\\\\' if len(specials) > 0: return re.sub(r'(' + r'|'.join(specials)+r'|'+escape + r')', escape + r'\1', input_str) return re.sub(r'(' + escape + r')', escape + r'\1', input_str) def unquote(input_str, specials, escape='\\'): """Splits the input string |input_str| where special characters in the input |specials| are, if not quoted by |escape|, used as delimiters to split the string. The returned value is a list of strings of alternating non-specials and specials used to break the string. The list will always begin with a possibly empty string of non-specials, but may end with either specials or non-specials.""" assert len(escape) == 1 out = [] cur_out = [] cur_special = False lit_next = False for c in input_str: if cur_special: lit_next = (c == escape) if c not in specials or lit_next: cur_special = False out.append(''.join(cur_out)) if not lit_next: cur_out = [c] else: cur_out = [] else: cur_out.append(c) else: if lit_next: cur_out.append(c) lit_next = False else: lit_next = c == escape if c not in specials: if not lit_next: cur_out.append(c) else: out.append(''.join(cur_out)) cur_out = [c] cur_special = True out.append(''.join(cur_out)) return out