@@ -222,12 +222,16 @@ def _guess_quote_and_delimiter(self, data, delimiters):
222222 this way.
223223 """
224224
225+ # The body of a quoted field ends at the first quote which is
226+ # not doubled, as it does for a reader. A lazy ".*?" scans to
227+ # the end of the sample instead, from every start: quadratically.
228+ body = r'(?:(?P=quote){2}|(?!(?P=quote)).)*+'
225229 matches = []
226- for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*? (?P=quote)(?P=delim)' , # ,".*? ",
227- r'(?:^|\n)(?P<quote>["\']).*? (?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)' , # ".*? ",
228- r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*? (?P=quote)(?:$|\n)' , # ,".*? "
229- r'(?:^|\n)(?P<quote>["\']).*? (?P=quote)(?:$|\n)' ): # ".*? " (no delim, no space)
230- regexp = re .compile (restr , re .DOTALL | re .MULTILINE )
230+ for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\'])%s (?P=quote)(?P=delim)' , # ,"... ",
231+ r'(?:^|\n)(?P<quote>["\'])%s (?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)' , # "... ",
232+ r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\'])%s (?P=quote)(?:$|\n)' , # ,"... "
233+ r'(?:^|\n)(?P<quote>["\'])%s (?P=quote)(?:$|\n)' ): # "... " (no delim, no space)
234+ regexp = re .compile (restr % body , re .DOTALL | re .MULTILINE )
231235 matches = regexp .findall (data )
232236 if matches :
233237 break
0 commit comments