Php 正则表达式匹配从换行符到括号以及搜索词的所有内容

Php 正则表达式匹配从换行符到括号以及搜索词的所有内容,php,regex,Php,Regex,我们正试图解析90年代基于DOS的会计软件输出的信息,以便将其转换并上传到更新的系统。它主要是与每个会计分录相关的信息,并通过随机制表符、换行符等输出。如下所示: #Ch. No. 209488 #Rt. Date 12-09-1997 #Bank: Citibank (R:2379;L:28) #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28) #Ch. No. 8

我们正试图解析90年代基于DOS的会计软件输出的信息,以便将其转换并上传到更新的系统。它主要是与每个会计分录相关的信息,并通过随机制表符、换行符等输出。如下所示:

#Ch. No. 209488 #Rt. Date 12-09-1997 #Bank: Citibank (R:2379;L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;
L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
#Bank: Citibank (R:2432;
L:28
)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
        #Bank: Citibank (R:2432;
    L:28
)
但是,很明显,每个条目的信息都从一个新行开始,以一个

如何编写一个从该行开始寻找术语一直到
的正则表达式

例如,在上面的数据中,我们使用
preg\u match\u all('/^.*\b(?:Dr)\b.*$/m',$dos,$matches)查找字符串
Dr
,它匹配如下:

Array
(
    [0] => Array
        (
            [0] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;
            [1] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
            [2] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
        )

)
从数组中的第二个结果可以看出,它被省略了
#Bank:Citibank(R:2432;L:28)
,因为它位于单独的一行上,但该数据仍然是它上面那一行的一部分

如何修改我们使用的正则表达式以匹配下一行(无论它是在同一行还是下一行,甚至是下面几行)?因此,结果将是:

Array
(
    [0] => Array
        (
            [0] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;L:28)
            [1] => #Ch. No. 759263 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;L:28)
            [2] => #Ch. No. 395159 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;L:28)
        )

)
您可以使用
[^
匹配除括号外的任何字符,括号也将匹配换行符

匹配后,可以用单个空格替换所有空白字符

^.*\bDr\b[^()]*\([^()]+\)
那会匹配的

  • ^
    字符串的开头
  • *\bDr\b
    匹配除换行符以外的任何字符的0+倍,然后在单词边界之间匹配Dr(或匹配
    \Dr\b
    ,如果它总是以
    开头)
  • [^()]*
    匹配0+乘以除括号外的任何字符
  • \(
    匹配
  • [^()]+
    匹配除括号外的任何字符的1+倍(如果必须至少有一个字符不是
  • \)
    匹配
|

比如说

$re = '/^.*\bDr\b[^()]*\([^()]+\)/m';
$str = '#Ch. No. 209488 #Rt. Date 12-09-1997 #Bank: Citibank (R:2379;L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;
L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
#Bank: Citibank (R:2432;
L:28
)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
        #Bank: Citibank (R:2432;
    L:28
)';

$result = preg_match_all($re, $str, $matches);
$result = array_map(function($x) {
    return preg_replace("/\s+/", ' ', $x);
}, $matches[0]);
print_r($result);
输出

Array
(
    [0] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28)
    [1] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28 )
    [2] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28 )
)
您可以使用
[^
匹配除括号外的任何字符,括号也将匹配换行符

匹配后,可以用单个空格替换所有空白字符

^.*\bDr\b[^()]*\([^()]+\)
那会匹配的

  • ^
    字符串的开头
  • *\bDr\b
    匹配除换行符以外的任何字符的0+倍,然后在单词边界之间匹配Dr(或匹配
    \Dr\b
    ,如果它总是以
    开头)
  • [^()]*
    匹配0+乘以除括号外的任何字符
  • \(
    匹配
  • [^()]+
    匹配除括号外的任何字符的1+倍(如果必须至少有一个字符不是
  • \)
    匹配
|

比如说

$re = '/^.*\bDr\b[^()]*\([^()]+\)/m';
$str = '#Ch. No. 209488 #Rt. Date 12-09-1997 #Bank: Citibank (R:2379;L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432;
L:28)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
#Bank: Citibank (R:2432;
L:28
)

#Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997
        #Bank: Citibank (R:2432;
    L:28
)';

$result = preg_match_all($re, $str, $matches);
$result = array_map(function($x) {
    return preg_replace("/\s+/", ' ', $x);
}, $matches[0]);
print_r($result);
输出

Array
(
    [0] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28)
    [1] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28 )
    [2] => #Ch. No. 884273 #Dr. Date 10-09-1997 #Ch. Dep. 14-09-1997 #Bank: Citibank (R:2432; L:28 )
)

根据@CBroe的评论,我得出以下结论:

/(#[^\)\n]*(?:#Dr.*\)\n*)/gsU

  • #[^\)\n]*
    ->以
    #
    开头,并防止搜索通过
    \n
    的所有字符(新行)

  • (?:#Dr)
    ->无捕获组中的搜索字符串

  • *\)\n*
    ->继续,直到遇到
    \n
    (新行)

  • gsU
    ->使用的标志:g:全局搜索,s:匹配新行,U:取消标记量词


根据@CBroe的评论,我得出了以下结论:

/(#[^\)\n]*(?:#Dr.*\)\n*)/gsU

  • #[^\)\n]*
    ->以
    #
    开头,并防止搜索通过
    \n
    的所有字符(新行)

  • (?:#Dr)
    ->无捕获组中的搜索字符串

  • *\)\n*
    ->继续,直到遇到
    \n
    (新行)

  • gsU
    ->使用的标志:g:全局搜索,s:匹配新行,U:取消标记量词