$escape 參數完全不直觀,但它並沒有壞掉。以下是 fgetcsv() 行為的分解。在範例中,我使用底線 (_) 來顯示空格,並使用括號 ([]) 來顯示個別欄位
- 如果每個欄位中的前導空白緊接在 enclosure 之前,則會被移除: ___"foo" -> [foo]
- 每個欄位只能有一個 enclosure,儘管它會與結束 enclosure 和下一個分界符號/新行之間出現的任何資料串連,包括任何尾端空白 ___"foo"_"bar"__ -> [foo_"bar"__]
- 如果欄位不是以(前導空白 +)enclosure 開頭,則整個欄位會被解讀為原始資料,即使 enclosure 字元出現在欄位中的其他位置: _foo"bar"_ -> [_foo"bar"_]
- 分界符號不能在 enclosure 外面被跳脫,它們必須被 enclosure 包起來。分界符號不需要在 enclosure 內被跳脫:"foo,bar","baz,qux" -> [foo,bar][baz,qux]; foo\,bar -> [foo\][bar]; "foo\,bar" -> [foo\,bar]
- 單一 enclosure 內的雙 enclosure 會被轉換為單一 enclosure:"foobar" -> [foobar]; "foo""bar" -> [foo"bar]; """foo""" -> ["foo"]; ""foo"" -> [foo""] (空的 enclosure 後面跟著原始資料)
- $escape 參數按預期工作,但與 enclosure 不同,它不會被反跳脫。必須在程式碼的其他地方反跳脫資料: "\"foo\"" -> [\"foo\"]; "foo\"bar" -> [foo\"bar]
注意:以下數據(這是一個非常常見的問題)無效:「\」。它的結構等同於「@」,換句話說,它是一個開放的封閉符、一些數據,然後沒有閉合封閉符。
可以使用以下函數來獲得預期的行為
<?php
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;
}
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;
}
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;
}
?>
警告:理想情況下,封閉符號外不應該有任何未跳脫的跳脫字元;欄位應該被封閉並跳脫。如果有任何未跳脫的跳脫字元,它們最終也可能會被移除,具體取決於所使用的函數。