Split a string up according to Unix shell-like rules for quotes and backslashes. In short: words are delimited by spaces, as long as those spaces are not escaped by a backslash, or inside a quoted string. Single and double quotes are equivalent, and the quote characters can be backs
(s)
| 111 | _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') |
| 112 | |
| 113 | def split_quoted (s): |
| 114 | """Split a string up according to Unix shell-like rules for quotes and |
| 115 | backslashes. In short: words are delimited by spaces, as long as those |
| 116 | spaces are not escaped by a backslash, or inside a quoted string. |
| 117 | Single and double quotes are equivalent, and the quote characters can |
| 118 | be backslash-escaped. The backslash is stripped from any two-character |
| 119 | escape sequence, leaving only the escaped character. The quote |
| 120 | characters are stripped from any quoted string. Returns a list of |
| 121 | words. |
| 122 | """ |
| 123 | |
| 124 | # This is a nice algorithm for splitting up a single string, since it |
| 125 | # doesn't require character-by-character examination. It was a little |
| 126 | # bit of a brain-bender to get it working right, though... |
| 127 | if _wordchars_re is None: _init_regex() |
| 128 | |
| 129 | s = s.strip() |
| 130 | words = [] |
| 131 | pos = 0 |
| 132 | |
| 133 | while s: |
| 134 | m = _wordchars_re.match(s, pos) |
| 135 | end = m.end() |
| 136 | if end == len(s): |
| 137 | words.append(s[:end]) |
| 138 | break |
| 139 | |
| 140 | if s[end] in string.whitespace: # unescaped, unquoted whitespace: now |
| 141 | words.append(s[:end]) # we definitely have a word delimiter |
| 142 | s = s[end:].lstrip() |
| 143 | pos = 0 |
| 144 | |
| 145 | elif s[end] == '\\': # preserve whatever is being escaped; |
| 146 | # will become part of the current word |
| 147 | s = s[:end] + s[end+1:] |
| 148 | pos = end+1 |
| 149 | |
| 150 | else: |
| 151 | if s[end] == "'": # slurp singly-quoted string |
| 152 | m = _squote_re.match(s, end) |
| 153 | elif s[end] == '"': # slurp doubly-quoted string |
| 154 | m = _dquote_re.match(s, end) |
| 155 | else: |
| 156 | raise RuntimeError("this can't happen (bad char '%c')" % s[end]) |
| 157 | |
| 158 | if m is None: |
| 159 | raise ValueError("bad string (mismatched %s quotes?)" % s[end]) |
| 160 | |
| 161 | (beg, end) = m.span() |
| 162 | s = s[:beg] + s[beg+1:end-1] + s[end:] |
| 163 | pos = m.end() - 2 |
| 164 | |
| 165 | if pos >= len(s): |
| 166 | words.append(s) |
| 167 | break |
| 168 | |
| 169 | return words |
| 170 |
no test coverage detected
searching dependent graphs…