note 120104 added to function.fgetcsv

From: Date: Tue, 01 Nov 2016 01:26:43 +0000
Subject: note 120104 added to function.fgetcsv
Groups: php.notes 
Request: Send a blank email to php-notes+get-206997@lists.php.net to get a copy of this message
The $escape parameter is completely unintuitive, but it is not broken. Here is a breakdown of fgetcsv()'s behaviour. In the examples I've used underscores (_) to show spaces and brackets ([]) to show individual fields: - Leading whitespace in each field will be stripped if it comes immediately before an enclosure: ___"foo" -> [foo] - There can only be one enclosure per field, although it will be concatenated with any data that appears between the end enclosure and the next delimiter/new line, including any trailing whitespaces ___"foo"_"bar"__ -> [foo_"bar"__] - If the field does not start with (leading whitespace +) an enclosure, the whole field is interpreted as raw data, even if enclosure characters appear elsewhere within the field: _foo"bar"_ -> [_foo"bar"_] - Delimiters cannot be escaped outside enclosures, they have to be enclosed instead. Delimiters don't need to be escaped inside enclosures: "foo,bar","baz,qux" -> [foo,bar][baz,qux]; foo\,bar -> [foo\][bar]; "foo\,bar" -> [foo\,bar] - Double enclosures inside single enclosures are converted to single enclosures: "foobar" -> [foobar]; "foo""bar" -> [foo"bar]; """foo""" -> ["foo"]; ""foo"" -> [foo""] (empty enclosure followed by raw data) - The $escape parameter works as expected, but unlike enclosures DOES NOT get unescaped. It is necessary to unescape the data elsewhere in the code: "\"foo\"" -> [\"foo\"]; "foo\"bar" -> [foo\"bar] Note: the following data (which is a very common problem) is invalid: "\". Its structure is equivalent to "@ or in other words, an open enclosure, some data and no closing enclosure. The following functions can be used to get the expected behaviour: <?php // Removes escape characters before both enclosures and escapes, but leaves everything else untouched, similiar to single quoting function fgetcsv_unescape_enclosures_and_escapes($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') { $fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape); if ($fields) { $regex_enclosure = preg_quote($enclosure); $regex_escape = preg_quote($escape); $fields = preg_replace("/{$regex_escape}({$regex_enclosure}|{$regex_escape})/", '$1', $fields); } return $fields; } // Does NOT remove a lone escape character at the end of a field function fgetcsv_unescape_all($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') { $fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape); if ($fields) { $regex_escape = preg_quote($escape); $fields = preg_replace("/{$regex_escape}(.)/s", '$1', $fields); } return $fields; } // Removes lone escape characters at the end of fields function fgetcsv_unescape_all_strip_last($fh, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\') { $fields = fgetcsv($fh, $length, $delimiter, $enclosure, $escape); if ($fields) { $regex_escape = preg_quote($escape); $fields = preg_replace("/{$regex_escape}(.?)/s", '$1', $fields); } return $fields; } ?> Caution: ideally, there shouldn't be any unescaped escape characters outside enclosures; the field should be enclosed and escaped instead. If there are any, they could end up being removed as well, depending on the function used. ---- Server IP: 72.52.91.14 Probable Submitter: 49.177.154.6 ---- Manual Page -- http://php.net/manual/en/function.fgetcsv.php Edit -- https://master.php.net/note/edit/120104 Del: integrated -- https://master.php.net/note/delete/120104/integrated Del: useless -- https://master.php.net/note/delete/120104/useless Del: bad code -- https://master.php.net/note/delete/120104/bad+code Del: spam -- https://master.php.net/note/delete/120104/spam Del: non-english -- https://master.php.net/note/delete/120104/non-english Del: in docs -- https://master.php.net/note/delete/120104/in+docs Del: other reasons-- https://master.php.net/note/delete/120104 Reject -- https://master.php.net/note/reject/120104 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#206997) next »