Looks for text enclosed between two identical quotes (the probable quotechar) which are preceded and followed by the same character (the probable delimiter). For example: ,'some text', The quote with the most wins, same with the delim
(self, data, delimiters)
| 268 | |
| 269 | |
| 270 | def _guess_quote_and_delimiter(self, data, delimiters): |
| 271 | """ |
| 272 | Looks for text enclosed between two identical quotes |
| 273 | (the probable quotechar) which are preceded and followed |
| 274 | by the same character (the probable delimiter). |
| 275 | For example: |
| 276 | ,'some text', |
| 277 | The quote with the most wins, same with the delimiter. |
| 278 | If there is no quotechar the delimiter can't be determined |
| 279 | this way. |
| 280 | """ |
| 281 | import re |
| 282 | |
| 283 | matches = [] |
| 284 | for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?", |
| 285 | r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?", |
| 286 | r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)', # ,".*?" |
| 287 | r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) |
| 288 | regexp = re.compile(restr, re.DOTALL | re.MULTILINE) |
| 289 | matches = regexp.findall(data) |
| 290 | if matches: |
| 291 | break |
| 292 | |
| 293 | if not matches: |
| 294 | # (quotechar, doublequote, delimiter, skipinitialspace) |
| 295 | return ('', False, None, 0) |
| 296 | quotes = {} |
| 297 | delims = {} |
| 298 | spaces = 0 |
| 299 | groupindex = regexp.groupindex |
| 300 | for m in matches: |
| 301 | n = groupindex['quote'] - 1 |
| 302 | key = m[n] |
| 303 | if key: |
| 304 | quotes[key] = quotes.get(key, 0) + 1 |
| 305 | try: |
| 306 | n = groupindex['delim'] - 1 |
| 307 | key = m[n] |
| 308 | except KeyError: |
| 309 | continue |
| 310 | if key and (delimiters is None or key in delimiters): |
| 311 | delims[key] = delims.get(key, 0) + 1 |
| 312 | try: |
| 313 | n = groupindex['space'] - 1 |
| 314 | except KeyError: |
| 315 | continue |
| 316 | if m[n]: |
| 317 | spaces += 1 |
| 318 | |
| 319 | quotechar = max(quotes, key=quotes.get) |
| 320 | |
| 321 | if delims: |
| 322 | delim = max(delims, key=delims.get) |
| 323 | skipinitialspace = delims[delim] == spaces |
| 324 | if delim == '\n': # most likely a file with a single column |
| 325 | delim = '' |
| 326 | else: |
| 327 | # there is *no* delimiter, it's a single column of quoted data |