PHP in_array 只找到最后一个数组元素

PHP in_array is only finding the last array element

以下 PHP 代码将多行字符串分解为数组。然后使用三个if语句检查数组中是否存在特定行,如果存在则回显相应的文本。

$multiline_string = 'First line
Second line
Third line';

$array = explode("\n", $multiline_string);

if (in_array('First line', $array))
{
    echo 'First line exists.';
}

if (in_array('Second line', $array))
{
    echo 'Second line exists.';
}

if (in_array('Third line', $array))
{
    echo 'Third line exists.';
}

问题是只有 Third line exists. 被回显,这意味着在数组中找不到第一行和第二行。

但是我使用 print_r($array) 进行了调试并得到了这个输出:

Array
(
    [0] => First line
    [1] => Second line
    [2] => Third line
)

所以数组中确实存在第一行和第二行。为什么 in_array 函数找不到它们?

试试 preg_split。它允许您使用正则表达式而不是精确的字符串匹配。

$multiline_string = 'First line
Second line
Third line';

$array = preg_split("/\r?\n/", $multiline_string);

if (in_array('First line', $array))
{
    echo 'First line exists.';
}

if (in_array('Second line', $array))
{
    echo 'Second line exists.';
}

if (in_array('Third line', $array))
{
    echo 'Third line exists.';
}

如果你使用双引号而不是单引号并添加回车 return \r ,它将打印出三行(注意我们没有将 \r 用于第三行)

<?php

$multiline_string = 'First line
Second line
Third line';

$array = explode("\n", $multiline_string);

dd($array);

if (in_array("First line\r", $array)){ //here we added a carriage return
    echo 'First line exists.'.'<br>';
}

if (in_array("Second line\r", $array)){ //here we added a carriage return
    echo 'Second line exists.'.'<br>';
}

if (in_array("Third line", $array)){ //here we did not
    echo 'Third line exists.'.'<br>';
}

function dd($something){
    echo '<pre>';
    var_dump($something);
    echo '</pre>';
}

输出将是:

array(3) {  
  [0]=>  
  string(11) "First line  
"  
  [1]=>  
  string(12) "Second line  
"  
  [2]=>  
  string(10) "Third line"  
}

First line exists.

Second line exists.

Third line exists.

背景

要了解发生了什么,您需要了解关于如何在文本文件中表示行尾的约定。

  • 在 Unix/Apple 机器上生成的文本文件通常使用单个换行符分隔行:\n.
  • 在 Windows 机器上生成的文本文件通常用两个字符分隔行,carriage-return + line-feed: \r\n.
  • 在非常老的 Apple 机器上生成的文本文件通常用回车 return 字符分隔行:\r。你可能不需要担心这个,因为它在实践中很少遇到。

维基百科有 a good summary that explains the history of these different standards.

你的问题

您的示例文件似乎是在 Windows 上创建的,因此每行之间有两个字符。这意味着当您在 \nexplode() 时,除了最后一行之外的每一行都将在末尾包含一个不可见的 \r 字符。这就是为什么在您的示例中只有最后一行匹配。

解决方案

根据您的多行字符串数据的来源,有几种解决方案。

如果您的情况如您的示例所示,其中字符串被定义为您控制的文件中的文字字符串,您有两个选择:

  1. 转换文件以使用 Unix 风格的行结尾。大多数文本 editors/IDEs 允许您通过菜单选项执行此操作。您只需为每个文件执行一次此操作(假设您在进行更改后保存它)。如果您进行此更改,您当前的代码将按原样工作。
  2. 更新您的代码以使用 $array = explode("\r\n", $multiline_string); 以便您根据 Windows 行结尾展开。

另一方面,如果您的数据来自用户输入,那么您应该对其进行编码以处理两种类型的行尾1。这里也有几个选项:

  1. 确保执行拆分的代码可以识别两种行结束样式。最简单的方法是用 $array = preg_split("/\r?\n/", $multiline_string) 替换 explode() 调用,这将在 \n\r\n.
  2. 的任何实例上爆炸
  3. 将一种行结束样式转换为另一种行结束样式,以便您了解正在使用的行结束样式,然后像以前一样使用 explode()。例如,$multiline_string = str_replace("\r\n", "\n", $multiline_string);。如果您稍后要对字符串执行其他操作,则此方法更可取,例如将其存储在数据库中,因为这意味着您只需处理一次,而不必在所有情况下都处理这两种可能性。

1 或者所有三种类型,如果你想彻底的话。这是 reader...

的练习