preg_match_all 为每个匹配循环,验证是不是为空以设置空值以插入表 mysql

Posted

技术标签:

【中文标题】preg_match_all 为每个匹配循环,验证是不是为空以设置空值以插入表 mysql【英文标题】:preg_match_all loop for each match, verify if empty to set null values to insert in table mysqlpreg_match_all 为每个匹配循环,验证是否为空以设置空值以插入表 mysql 【发布时间】:2022-01-01 12:16:10 【问题描述】:

我有 10 行要从文件文本中提取其他行,有些是空的但存在,有些不存在但无论如何我必须插入它们,使用正则表达式可以将文本分成 10 组,我使用 preg_match_all 匹配组并生成一个匹配的数组,但如果行不存在不匹配,我希望插入值组插入到 mysql 表中,如果值为空,则设置为 NULL。

我只需要它们的值,但首先验证键是否存在并为此添加缺失的键和 NULL 值。

如果值为空,则设置NULL,如果该组在文本文件中不存在,则添加一个值以设置NULL以插入到表mysql中。

请参阅更新问题

我应该使用 array_push、array_key_exists 还是在正则表达式中为每个组分配一个名称?

最后,如何循环每个匹配项?使用 preg_match_all 只生成一个完全匹配的数组,但我的表 mysql 只有 10 列,每个组正则表达式一列。

更新问题:我改写了帖子 11/24/21 01.00

例如完整的数据是 10 行

/*
First Name         :NameAAAAAA
LINE TO EXCLUDE    : this line is to exclude     
Last Name          :LastAAAAAA
LINE TO EXCLUDE    : this line is to exclude
Gender = (F/M)     :
ANOTHER LINE TO EXCLUDE : this line is to exclude                             
        TEST INFO 1      :TI1AAAAAA
        ANOTHER LINE TO EXCLUDE  : this line is to exclude             
        TEST INFO 2      :       
        TEST INFO 3      :TI3AAAAAA
First Name         :NameBBBBBB
LINE TO EXCLUDE    : this line is to exclude     
Last Name          :LastBBBBBB
LINE TO EXCLUDE    : this line is to exclude
Gender = (F/M)     :
First Name         :NameCCCCCC
LINE TO EXCLUDE    : this line is to exclude     
Last Name          :LastCCCCCC
LINE TO EXCLUDE    : this line is to exclude
Gender = (F/M)     :M
ANOTHER LINE TO EXCLUDE : this line is to exclude                             
        TEST INFO 1      :
        ANOTHER LINE TO EXCLUDE  : this line is to exclude             
        TEST INFO 2      :TI2CCCCCC       
        TEST INFO 3      :
*/

使用正则表达式仅提取行(6行):

https://regex101.com/r/hWzvOr/1

/.*(?:First Name).*|.*(?:Last Name).*|.*(?:Gender = \(F\/M\)).*|.*(?:TEST INFO 1).*|.*(?:TEST INFO 2).*|.*(?:TEST INFO 3).*/g

使用正则表达式模式提取后的以下字符串:有可能发现不存在的行(参见 NameBBBBBB 组中的 TEST INFO 1-2-3)

$str = '
First Name         :NameAAAAAA    
Last Name          :LastAAAAAA                 
Gender = (F/M)     :                            
        TEST INFO 1   :TI1AAAAAA     
        TEST INFO 2   :       
        TEST INFO 3   :TI3AAAAAA  
First Name         :NameBBBBBB   
Last Name          :LastBBBBBB                 
Gender = (F/M)     :                                                                                 
First Name         :NameCCCCCC   
Last Name          :LastCCCCCC                 
Gender = (F/M)     :M                            
        TEST INFO 1   :     
        TEST INFO 2   :TI2CCCCCC       
        TEST INFO 3   : 
';

如果不存在(不匹配)通过动态创建键并将值设置为NULL,如果值为空设置为NULL。

必须生成,(请参阅组 NameBBBBBB 中的 TEST INFO 1-2-3)

Array
(
    [0] => Array
        (
            [0] => First Name         :NameAAAAAA    
            [1] => Last Name          :LastAAAAAA                 
            [2] => Gender = (F/M)     :                            
            [3] =>         TEST INFO 1   :TI1AAAAAA     
            [4] =>         TEST INFO 2   :       
            [5] =>         TEST INFO 3   :TI3AAAAAA 
            [6] => First Name         :NameBBBBBB    
            [7] => Last Name          :LastBBBBBB                 
            [8] => Gender = (F/M)     : 
            [9] =>         TEST INFO 1   :                        
            [10] =>        TEST INFO 2   :
            [11] =>        TEST INFO 3   :                             
            [12] => First Name         :NameCCCCCC    
            [13] => Last Name          :LastCCCCCC                 
            [14] => Gender = (F/M)     : M                           
            [15] =>         TEST INFO 1   :                        
            [16] =>         TEST INFO 2   :TI2CCCCCC
            [17] =>         TEST INFO 3   :                                          
        )

)

如果在正则表达式中不匹配,如何创建密钥?循环生成一个包含所有数据的数组,但我将每个循环的 6 行值插入到一个 6 列的表中到 mysql 中?

提前致谢。

问候。

意大利。

【问题讨论】:

我玩过它和came up with this (demo)。也许有用。 感谢您的回答,我改写了帖子,数据只有从匹配正则表达式的行中提取的相同行,而不是所有数据。请在帖子中查看我的更新问题。再次感谢。 【参考方案1】:

我将分多个步骤处理:

$str = '
      APPLICATION ID                   :AAAAA#AA#0101       
      STATUS P=PENDING/A=ACTIVE        :A                    
      VALID-TO DATE                    :711231               
      APPLICATION TYPE (A/G)           :A                    
      DESCRIPTIVE TEXT                 :DESC folder AAAAA    
      OWNER ID                         :               
      RANDOM INFO                      :                     
            PERIOD OR RUN CYCLE GROUP NAME   :QAZ123XX        
            RUN CYCLE VALID-FROM             :711230          
            RUN CYCLE VALID-TO               :711231          
            RUN CYCLE DESCRIPTION            :MANUAL ORDER    
            RUN RANDOM IFO                   :                
      APPLICATION ID                   :BBBBB#BB#0101       
      STATUS P=PENDING/A=ACTIVE        :A                    
      VALID-TO DATE                    :711231               
      APPLICATION TYPE (A/G)           :A                    
      DESCRIPTIVE TEXT                 :                     
      OWNER ID                         :OWNER1               
      RANDOM INFO                      :                     
';

$groups = explode('APPLICATION ID', $str);
foreach ($groups as $group) 
    echo "----\n";
    $hash = [];
    if (empty($group)) continue;
    $group = 'APPLICATION ID' . $group;
    $lines = preg_split("/\n/", $group);
    foreach($lines as $line) 
        $kv = explode(':', $line);
       if (count($kv) == 2 && trim($kv[1]) != '')
            $hash[trim($kv[0])] = trim($kv[1]);
    
    print_r($hash);

    // TODO:  Build an INSERT with just the values in $hash
    // Meanwhile, each column should be `DEFAULT NULL`.

产量:

----
Array
(
)
----
Array
(
    [APPLICATION ID] => AAAAA#AA#0101
    [STATUS P=PENDING/A=ACTIVE] => A
    [VALID-TO DATE] => 711231
    [APPLICATION TYPE (A/G)] => A
    [DESCRIPTIVE TEXT] => DESC folder AAAAA
    [PERIOD OR RUN CYCLE GROUP NAME] => QAZ123XX
    [RUN CYCLE VALID-FROM] => 711230
    [RUN CYCLE VALID-TO] => 711231
    [RUN CYCLE DESCRIPTION] => MANUAL ORDER
)
----
Array
(
    [APPLICATION ID] => BBBBB#BB#0101
    [STATUS P=PENDING/A=ACTIVE] => A
    [VALID-TO DATE] => 711231
    [APPLICATION TYPE (A/G)] => A
    [OWNER ID] => OWNER1
)

另一个提示:NULLIF(?, '')

【讨论】:

感谢您的回答,在 Yields 部分中,在第一个数组中缺少键 OWNER ID :具有空值,在第二个数组中应该有数组键并且值是空的(不存在)[描述性文本] [PERIOD OR RUN CYCLE GROUP NAME] => [RUN CYCLE VALID-FROM] => [RUN CYCLE VALID-TO] => [RUN CYCLE DESCRIPTION] =>,我在您的回答中读到,这样做会丢失。请在帖子中查看我的更新问题。再次感谢。【参考方案2】:
    构建一个数组,将所有需要的键和值设置为 null:
$columns = [
    'APPLICATION ID',
    'STATUS P=PENDING/A=ACTIVE',
    /*...*/
    'RUN CYCLE DESCRIPTION'
];

$keys = array_fill_keys($columns, null);
    构建一个模式来提取字符串中存在的键和值。为此,将所有需要的键放入模式中是完全没用的,您只需要使用捕获组(在此处命名)将键与每个匹配的值隔离开(注意 value 组是可选):
$pat = '~^ \h*+ (?<key> [^:\n]* [^:\s] ) \h* : (?<value> \S+ (?:\h+\S+)* )? ~xm';
    preg_match_allPREG_UNMATCHED_AS_NULL 标志一起使用:当可选 组不匹配时,返回值为null 而不是空字符串。 使用preg_match_all 匹配结果,使用$matches['key']$matches['value'] 子数组构建一个关联数组(请注意,这个数组与数组$keys 具有相同的键,但最终缺少一些键)。 那么你所要做的就是将$keys数组与这个新数组合并,得到一个包含你感兴趣的键/值对的关联数组。
if ( preg_match_all($pat, $yourstring, $matches, PREG_UNMATCHED_AS_NULL) ) 
    $result = array_combine($matches['key'], $matches['value']);
    // $result = array_intersect_key($result, $keys); // if you need to exclude some key/value pairs from the string
    $result = array_merge($keys, $result);

1,2,3 Aquafresh® 3

【讨论】:

感谢您的回答,我改写了帖子,数据只有从匹配正则表达式的行中提取的相同行,而不是所有数据。在您的步骤 3) 中,$result 数组中只有一个最后一个循环,如果这些行不存在,则该信息将与前一个循环中的数据合并。请在帖子中查看我的更新问题。再次感谢。 @italo_pm:如果您有要排除的行,这不是问题,请在array_merge 行之前添加$result = array_intersect_key($result, $keys); @italo_pm:在应用脚本之前拆分您的字符串,并立即处理一个块。 感谢 Casimir 的回答,使用 array_intersect_key 排除行工作正常,但最后一个数组 $result 只有最后一个结果循环而不是所有行循环,如何保存所有行循环? ` $result = array_combine($matches['key'], $matches['value']); $result = array_intersect_key($result, $keys); $result = array_merge($keys, $result); print_r( $result, true ) Array ( [First Name] => NameCCCCCC [Last Name] => LastCCCCCC [Gender = (F/M)] => M [TEST INFO 1] => [TEST INFO 2] => TI2CCCCCC [测试信息 3] => )` 再次感谢。 @italo_pm:存储每个块的结果:3v4l.org/5GvSS(或在循环中一次将它们发送到数据库)。

以上是关于preg_match_all 为每个匹配循环,验证是不是为空以设置空值以插入表 mysql的主要内容,如果未能解决你的问题,请参考以下文章

使用 preg_match_all() 获取重复匹配

为啥 preg_match_all 返回两个匹配项?

突出显示 preg_match_all() 的主题字符串中的匹配结果

PHP 正则表达式匹配 preg_match 与 preg_match_all 函数

preg_match_all() php正则匹配图片路径,怎么取完整的图片链接。带http开头,求解决

使用 preg_match_all PHP 限制结果数