【问题标题】:Parsing a complicated two files解析复杂的两个文件
【发布时间】:2015-02-23 20:25:17
【问题描述】:

文件 1 值:

....
Group   2012_fln
{
    vnum    103
    Type    mixed
    1   1167    1   2
    2   7731    1   2
    3   3561    1   2
    4   8613    1   3
}

Group   7612_edb
{
    vnum    104
    Type    other
    1   6312    1   90
    2   5241    5   45
....

文件 2 值:

....
1167    ºÎȰÀı´Ş°¿
7731    ÀÌÆÄÀÇ
3561    »¡°£»ö
....

所有值都已用 TAB 分隔。顺便说一句,这两个文件中都有数千个值。

所以这是我的问题:

我需要检查文件 1 上的值。文件 2 中是否存在。 如果文件 2 的值中不存在 1167 或 7731 或 3561 或 8613 值。

我需要在每个小组中都这样做。如果不存在,我需要一个错误回显,例如;在 xxx 组中,xxx vnum 不存在。并继续到文件 1 的结尾。

我试图爆炸,但文件 1 中有很多语法,如 Group、{}、vnum、type 等。我知道,这很复杂,这就是我在这里写的原因。

我可以像这样解析我的 File 2 值:

$line = trim($line);

$token = explode("\t", $line);

if ("" == $token[0] or "VNUM" == $token[0])
    continue;

$vnum = $token[0];
$entry_name = $token[1];

所以,我真的需要一个很大的帮助,我在这个问题上花了我最后两天......我希望我解释得当。

【问题讨论】:

  • 你只关心匹配行与 4 个制表符分隔的数字吗?
  • 我只需要在第二个标签中获取数字;喜欢:1 1167 1 2,“1167”。
  • 你可以连续做两次爆炸。例如:第一个在'}' 上爆炸,第二个在换行符PHP_EOL 上。现在每个组都有一个数组。使用substr() 从除前五行之外的所有行中获取您想要的数字,您就完成了。

标签: php arrays file parsing explode


【解决方案1】:

我建议使用正则表达式来解析您的数据,因为看起来每一行都遵循某种格式。对于文件一,您可以设置一个表达式,如

^\t(\d+)\t(\d+)\t(\d+)\t(\d+)

这表示匹配一个制表符,后跟至少一个数字字符,四次。任何匹配的行都将是您关心的行。从那里,您对第二组感兴趣,或$2

对于文件二,您可能需要类似

^(\d+).*

这就是说,匹配至少一个开始行的数字,然后是其他任何数字。因此,您关心第一个(也是唯一一个)分组$1

从第一个文件或第二个文件构造一个数字映射,然后遍历另一个文件中的匹配项并检查该映射。

由于您使用的是 php,因此您可以将 preg_match 用于正则表达式 http://php.net/manual/en/function.preg-match.php

【讨论】:

    【解决方案2】:

    如果您只需要第二列并且所有需要值的行的格式都相同,请使用file_get_contents($file1) 将文件加载到字符串中并匹配该模式(4 个数字由空格分隔)。

    类似:

    preg_match_all('/^\s*\d+\s+(\d+)\s+\d+\s+\d+\s*$/m', $data, $matches);
    

    这会将$matches 设置为如下数组:

    Array
    (
        [0] => Array
            (
                [0] =>     1   1167    1   2
                [1] =>     2   7731    1   2
                [2] =>     3   3561    1   2
                [3] =>     4   8613    1   3
                [4] =>     1   6312    1   90
                [5] =>     2   5241    5   45
            )
    
        [1] => Array
            (
                [0] => 1167
                [1] => 7731
                [2] => 3561
                [3] => 8613
                [4] => 6312
                [5] => 5241
            )
    
    )
    

    $matches[1] 将是第二列中所有值的数组。您可以对 $matches[1] 进行 foreach 循环比较,以查看该值是否在第二个文件中。我建议先加载第二个文件并生成一个索引,这样当你遍历匹配项时,你可以检查是否array_key_exists($value, $file2Index)

    示例,每个请求:

    <?php
    //read the first file in as a string
    $file1 = file_get_contents("/path/to/file1");
    //read the second file in as an array
    $file2 = file("/path/to/file2");
    
    //index from file2 that we are going to build
    $file2Index = array();
    
    foreach($file2 as $line){
        //split the line
        $line = explode("\t", $line, 2);
        //validate the line, should be only 2 values after explode and first should be a number
        if(count($line) == 2 && is_numeric($line[0])){
            //add to index
            $file2Index[$line[0]] = $line[1];
        }
    }
    
    //now get all the values from file1 that we want (second column)
    preg_match_all('/^\s*\d+\s*(\d+)\s*\d+\s*\d+\s*$/m', $data, $matches);
    
    $file1Values = array_unique($matches[1]);
    
    //loop over the matches from column 2
    foreach($file1Values as $value){
        //check if the key doesn't exist
        if(!isset($file2Index[$value])){
            //echo error message
            echo "Value {$value} does not exist in file2<br>";
        }
    }
    

    【讨论】:

    • 您应该使用isset 而不是array_key_exists。这是(伪)常数运算与线性运算
    • @wilkesybear 只要您不想在值为空时返回假阴性,它就可以工作。在这种情况下,这可能不是问题,因为您将自己构建索引。
    • 对,好点。但由于“我们正在”创建数组,我们可以将每个值设为 'key' =&gt; true 以确保 isset 行为正确。
    • $file1 = file_get_contents("dataparser\file1.txt"); preg_match_all('/^\s*\d+\s*(\d+)\s*\d+\s*\d+\s*$/m', $file1, $matches); print_r ($matches[1]); 返回:Array ( [0] =&gt; 50721 [1] =&gt; 50723 [2] =&gt; 50721 [3] =&gt; 50723 [4]..... 好吧,我做了你的技术,我成功得到了Vnums,但是有很多重复的Vnums,如何防止重复数字?
    • 非常感谢,先生,您的代码中没有给出 $data 变量,那不应该是 $file1 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-12
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多