php 比较两个文本文件并输出非匹配记录

php Compare two text files and output NON matching records

提问人:mark.four 提问时间:3/24/2022 最后编辑:mark.four 更新时间:3/25/2022 访问量:913

问:

我有两个数据文本文件,第一个文件有 30 行数据,与第二个文本文件中的 30 行匹配,但除此之外,第一个文本文件还有两行附加行,当操作员将文件上传到目录时添加,我想找到不匹配的行并将它们放在与邮件输出相同的脚本中。

我正在尝试使用此代码,它将两个文件的内容输出到屏幕。

<?php


if ($file1 = fopen(".data1.txt", "r")) {
    while(!feof($file1)) { $textperline = fgets($file1);
         echo $textperline;
        echo "<br>";}

if ($file2 = fopen(".data.txt", "r")) {
    while(!feof($file2)) {$textperline1 = fgets($file2);
    echo $textperline1;
    echo "<br>";}

fclose($file1);
fclose($file2);
}}
 
?>

但是它输出整个数据列表,谁能帮忙只列出不匹配的行?

我的代码中两个文件的附加输出

我只想输出 file2 中的行,但不输出 file1 中的行

PHP 匹配

评论

1赞 CBroe 3/24/2022
这缺乏上下文,我们看不到您的变量$textperline和 $textperline 1 实际包含什么。请提供适当的最小可重现问题示例,包括适当的测试数据。(如果可以以这种方式重现问题,则可以通过字符串变量提供测试数据。
1赞 GetSet 3/24/2022
除了缺乏背景之外,它还缺乏明确的设计策略。例如,您想找到所有不同的 1:1 线吗?或者您想找到一个文件中不存在的任何行与另一个文件中不存在的任何行?例如 将 1:1 匹配 If We 假装字母都在新行上。但是,即使所有行都匹配,也不匹配 1:1。...也就是说,线条的顺序重要还是不重要?a b ca b cc b aa b c
0赞 mark.four 3/24/2022
行的顺序将保持不变,我只想输出 file2 中未出现在 file1 中的行
1赞 Selim Acar 3/25/2022
检查必须区分大小写吗?行的顺序是重要的还是只有内容重要?
1赞 Selim Acar 3/25/2022
我的意思是新行是否附加到文件的末尾2?

答:

0赞 Andrea Olivato 3/25/2022 #1

我的建议是将每个文件读入一个数组(一行=一个元素),然后用来比较它们。除非你有数百万行,否则这种方法是最简单的。array_diff

要重用您的代码,您可以通过以下方式将 2 个文件读取到两个数组中

$list1 = [];
$list2 = [];
if ($file1 = fopen(".data1.txt", "r")) {
    while (!feof($file1)) {
        $list1[] = trim(fgets($file1));
    }
    fclose($file1);
}

if ($file2 = fopen(".data.txt", "r")) {
    while (!feof($file2)) {
        $list2[] = trim(fgets($file2));
    }
    fclose($file2);
}

如果文件很小,您可以一次性读取它们,您还可以使用简化的语法。

$list1 = explode(PHP_EOL, file_get_contents(".data1.txt"));
$list2 = explode(PHP_EOL, file_get_contents(".data.txt"));

然后,无论您选择哪种方法,都可以按如下方式比较它们

$comparison = array_diff($list2, $list1);
foreach ($comparison as $line) {
    echo $line."<br />";
}

这将仅输出第二个数组中第一个数组中不存在的行。

确保带有附加行的那个是array_diff

0赞 Selim Acar 3/25/2022 #2

假设

这两个文件都不是很大,您可以一次将全部内容读入内存中。据此,您可以将以下代码放在顶部:

$file1 = "./data1.txt";
$file2 = "./data2.txt";
$linesOfFile1 = file($file1);
$linesOfFile2 = file($file2);
$newLinesInFile2 = [];

有几个情况,你在问题中没有提到。

案例 1

新行仅附加到 secode 文件。这种情况的解决方案是最简单的:file2

$numberOfRowsFile1 = count($linesOfFile1);
$numberOfRowsFile2 = count($linesOfFile1);
if($numberOfRowsFile2 > $numberOfRowsFile1)
{
    $newLinesInFile2 = array_slice($linesOfFile2, $numberOfRowsFile1);
}

案例 2

具有相同内容的行在每个文件中的位置可能不同。忽略同一文件中的重复行。

此外,区分大小写可能也起作用。这就是为什么应该对每行的内容进行哈希处理,以便进行更简单的比较。对于区分大小写和不区分大小写的比较,需要以下函数:

function buildHashedMap($array, &$hashedMap, $caseSensitive = true)
{
    foreach($array as $line)
    {
        $line = !$caseSensitive ? strtolower($line) : $line;
        $hash = md5($line);
        $hashedMap[$hash] = $line;
    }
}

区分大小写比较

$hashedLinesFile1 = [];
buildHashedMap($linesOfFile1, $hashedLinesFile1);

$hashedLinesFile2 = [];
buildHashedMap($linesOfFile2, $hashedLinesFile2);

$newLinesInFile2 = array_diff_key($hashedLinesFile2, $hashedLinesFile1);

不区分大小写的比较

$caseSensitive = false;
$hashedLinesFile1 = [];
buildHashedMap($linesOfFile1, $hashedLinesFile1, $caseSensitive);

$hashedLinesFile2 = [];
buildHashedMap($linesOfFile2, $hashedLinesFile2, $caseSensitive);

$newLinesInFile2 = array_diff_key($hashedLinesFile2, $hashedLinesFile1);