Определить тип EOL с помощью PHP

Ссылка: Это вопрос с ответами на вопрос. Он должен был делиться знаниями, стилем Q & A.

Как определить тип символа конца строки в PHP?

PS: Я писал этот код с нуля слишком долго, поэтому я решил поделиться этим с SO, плюс, я уверен, что кто-то найдет способы для улучшения.

Related of "Определить тип EOL с помощью PHP"

/** * Detects the end-of-line character of a string. * @param string $str The string to check. * @param string $default Default EOL (if not detected). * @return string The detected EOL, or default one. */ function detectEol($str, $default=''){ static $eols = array( "\0x000D000A", // [UNICODE] CR+LF: CR (U+000D) followed by LF (U+000A) "\0x000A", // [UNICODE] LF: Line Feed, U+000A "\0x000B", // [UNICODE] VT: Vertical Tab, U+000B "\0x000C", // [UNICODE] FF: Form Feed, U+000C "\0x000D", // [UNICODE] CR: Carriage Return, U+000D "\0x0085", // [UNICODE] NEL: Next Line, U+0085 "\0x2028", // [UNICODE] LS: Line Separator, U+2028 "\0x2029", // [UNICODE] PS: Paragraph Separator, U+2029 "\0x0D0A", // [ASCII] CR+LF: Windows, TOPS-10, RT-11, CP/M, MP/M, DOS, Atari TOS, OS/2, Symbian OS, Palm OS "\0x0A0D", // [ASCII] LF+CR: BBC Acorn, RISC OS spooled text output. "\0x0A", // [ASCII] LF: Multics, Unix, Unix-like, BeOS, Amiga, RISC OS "\0x0D", // [ASCII] CR: Commodore 8-bit, BBC Acorn, TRS-80, Apple II, Mac OS <=v9, OS-9 "\0x1E", // [ASCII] RS: QNX (pre-POSIX) //"\0x76", // [?????] NEWLINE: ZX80, ZX81 [DEPRECATED] "\0x15", // [EBCDEIC] NEL: OS/390, OS/400 ); $cur_cnt = 0; $cur_eol = $default; foreach($eols as $eol){ if(($count = substr_count($str, $eol)) > $cur_cnt){ $cur_cnt = $count; $cur_eol = $eol; } } return $cur_eol; } 

Заметки:

  • Нужно проверить тип кодировки
  • Нужно как-то знать, что мы можем быть в экзотической системе, такой как ZX8x (поскольку ASCII x76 является обычной буквой). @radu поднял хороший момент, в моем случае, не стоит стараться хорошо обращаться с системами ZX8x.
  • Должен ли я разделить функцию на две? mb_detect_eol() ( detect_eol() ) и detect_eol()

Не было бы проще просто заменить все, кроме новых строк, с помощью регулярных выражений ?

Точка соответствует одному символу, не заботясь о том, что это за символ. Единственным исключением являются символы новой строки.

Имея это в виду, мы делаем магию:

 $string = 'some string with new lines'; $newlines = preg_replace('/.*/', '', $string); // $newlines is now filled with new lines, we only need one $newline = substr($newlines, 0, 1); 

Не уверен, можем ли мы доверять регулярному выражению, чтобы сделать все это, но мне не с чем поучиться.

введите описание изображения здесь

Здесь уже предоставленные ответы предоставляют пользователю достаточную информацию. Следующий код (основанный на уже предоставленных андерверах) может помочь еще больше:

  • Он дает ссылку на найденный EOL
  • Обнаружение устанавливает также ключ, который может использоваться приложением к этой ссылке.
  • В нем показано, как использовать ссылку в служебном классе.
  • Показывает, как использовать его для обнаружения файла, возвращающего имя ключа найденного EOL.
  • Надеюсь, это будет полезно для всех вас.

     /** Newline characters in different Operating Systems The names given to the different sequences are: ============================================================================================ NewL Chars Name Description ----- ----------- -------- ------------------------------------------------------------------ LF 0x0A UNIX Apple OSX, UNIX, Linux CR 0x0D TRS80 Commodore, Acorn BBC, ZX Spectrum, TRS-80, Apple II family, etc LFCR 0x0A 0x0D ACORN Acorn BBC and RISC OS spooled text output. CRLF 0x0D 0x0A WINDOWS Microsoft Windows, DEC TOPS-10, RT-11 and most other early non-Unix and non-IBM OSes, CP/M, MP/M, DOS (MS-DOS, PC DOS, etc.), OS/2, ----- ----------- -------- ------------------------------------------------------------------ */ const EOL_UNIX = 'lf'; // Code: \n const EOL_TRS80 = 'cr'; // Code: \r const EOL_ACORN = 'lfcr'; // Code: \n \r const EOL_WINDOWS = 'crlf'; // Code: \r \n 

    затем используйте следующий код в статическом классе Утилита для обнаружения

     /** Detects the end-of-line character of a string. @param string $str The string to check. @param string $key [io] Name of the detected eol key. @return string The detected EOL, or default one. */ public static function detectEOL($str, &$key) { static $eols = array( Util::EOL_ACORN => "\n\r", // 0x0A - 0x0D - acorn BBC Util::EOL_WINDOWS => "\r\n", // 0x0D - 0x0A - Windows, DOS OS/2 Util::EOL_UNIX => "\n", // 0x0A - - Unix, OSX Util::EOL_TRS80 => "\r", // 0x0D - - Apple ][, TRS80 ); $key = ""; $curCount = 0; $curEol = ''; foreach($eols as $k => $eol) { if( ($count = substr_count($str, $eol)) > $curCount) { $curCount = $count; $curEol = $eol; $key = $k; } } return $curEol; } // detectEOL 

    а затем для файла:

     /** Detects the EOL of an file by checking the first line. @param string $fileName File to be tested (full pathname). @return boolean false | Used key = enum('cr', 'lf', crlf'). @uses detectEOL */ public static function detectFileEOL($fileName) { if (!file_exists($fileName)) { return false; } // Gets the line length $handle = @fopen($fileName, "r"); if ($handle === false) { return false; } $line = fgets($handle); $key = ""; <Your-Class-Name>::detectEOL($line, $key); return $key; } // detectFileEOL 

    Измените имя своего класса на свое имя для класса реализации (все статические члены).

    На основании ответа Охала.

    Это может вернуть один или два символа для EOL, например LF, CR + LF ..

      $eols = array_count_values(str_split(preg_replace("/[^\r\n]/", "", $string))); $eola = array_keys($eols, max($eols)); $eol = implode("", $eola); 

    Мой ответ, потому что я не мог сделать ни одну из них, ни одну из трансильвальд ,

     function detect_newline_type($content) { $arr = array_count_values( explode( ' ', preg_replace( '/[^\r\n]*(\r\n|\n|\r)/', '\1 ', $content ) ) ); arsort($arr); return key($arr); } 

    Объяснение:

    Общая идея в обоих предлагаемых решениях хороша, но детали реализации затрудняют полезность этих ответов.

    В самом деле, точкой этой функции является возврат типа новой строки, используемой в файле, и эта строка может быть длиной один или два символа .

    Это само по себе делает использование str_split() неправильным. Единственный способ правильно разрезать маркеры – использовать функцию, которая режет строку с переменной длиной, на основе обнаружения символов. Именно тогда вступает в игру explode() .

    Но для того, чтобы дать полезные маркеры, чтобы взорваться, необходимо заменить правильные символы в нужном количестве по правильному совпадению. И большая часть магии происходит в регулярном выражении.

    Необходимо учитывать 3 балла:

    1. используя .* как предложено ohaal не будет работать. Хотя это правда . не будет соответствовать символам новой строки, в системе, где \r не является символом новой строки или частью символа новой строки . (напоминание: мы обнаруживаем новые строки, потому что они могут отличаться от тех, что указаны в нашей системе, в противном случае нет смысла).
    2. заменяя /[^\r\n]*/ когда что-то будет «работать», чтобы текст исчезал, но будет проблемой, как только мы захотим иметь разделитель (поскольку мы удаляем все символы, кроме строк новой строки, любой символ, который не является символом новой строки, будет действительным разделителем). Отсюда идея создать совпадение с новой строкой и использовать обратную ссылку для этого совпадения в замене.
    3. Возможно, что в контенте несколько строк новой строки будут в строке. Однако мы не хотим группировать их в этом случае, так как они будут рассматриваться остальной частью кода как разные типы новых строк. Вот почему список новых строк явно указан в матче для обратной ссылки.