php - PHP in_array 只找到最后一个数组元素
问题描述
下面的 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
函数没有找到它们?
解决方案
背景
要了解发生了什么,您需要了解关于如何在文本文件中表示行尾的多种约定。
- 在 Unix/Apple 机器上生成的文本文件通常用一个换行符分隔行:
\n
. - 在 Windows 机器上生成的文本文件通常用两个字符分隔行,回车 + 换行:
\r\n
。 - 在非常旧的 Apple 机器上生成的文本文件通常用回车符分隔行:
\r
. 您可能不需要担心这一点,因为它在实践中很少遇到。
维基百科有一个很好的总结,解释了这些不同标准的历史。
你的问题
看起来您的示例文件是在 Windows 上创建的,因此每行之间有两个字符。这意味着当您explode()
在\n
除最后一行之外的每一行时,最后都会包含一个不可见\r
字符。这就是为什么在您的示例中只有最后一行匹配。
解决方案
对此有几个解决方案,具体取决于您的多行字符串数据的来源。
如果您的情况如示例中所示,其中字符串在您控制的文件中定义为文字字符串,您有两个选择:
- 将文件转换为使用 Unix 样式的行尾。大多数文本编辑器/IDE 允许您通过菜单选项执行此操作。您只需为每个文件执行一次(假设您在进行更改后保存它)。如果您进行此更改,您当前的代码将按原样工作。
- 更新要使用的代码,
$array = explode("\r\n", $multiline_string);
以便基于 Windows 行尾进行爆炸。
另一方面,如果您的数据来自用户输入,那么您应该对其进行编码以处理两种类型的行尾1。这里也有几个选项:
- 确保执行拆分的代码能够识别两种行尾样式。最简单的方法是将
explode()
调用替换为 ,这将在or$array = preg_split("/\r?\n/", $multiline_string)
的任何实例上爆炸。\n
\r\n
- 将一种行尾样式转换为另一种行尾样式,以便您知道正在使用的行尾样式,然后
explode()
像以前一样使用 。例如,$multiline_string = str_replace("\r\n", "\n", $multiline_string);
。如果您稍后要对字符串执行其他操作,例如将其存储在数据库中,则此方法更可取,因为这意味着您只需要处理一次,而不必在所有情况下都处理这两种可能性。
1或所有三种类型,如果你想彻底。这留给读者作为练习......
推荐阅读
- spring - 即使 OAuth2 验证失败,如何记录 http 请求/响应正文?
- html - 导航栏下划线悬停动画
- c# - 使用正则表达式 C# 搜索单词或类似单词
- amazon-eks - 如何在两个 EKS 服务之间共享 AWS NLB?
- java - 为什么 Maven 要使用 javax.persistence 而不是替代的休眠版本
- oracle - 无法在 SQL CREATE TABLE 命令中设置 INTEGER 数据类型的精度
- c# - 将键/值 XML 数据反序列化为 C# 对象
- ios - 找不到“UNUserNotificationCenterDelegate”的协议声明
- powershell - 带有方括号的路径的 Powershell 脚本
- android - 使用 HostnameVerifier 接口(Kotlin)的不安全实现的 Android 应用