【问题标题】:How to parse a mostly consistent filename into meaningful parts?如何将大部分一致的文件名解析为有意义的部分?
【发布时间】:2021-02-13 23:13:12
【问题描述】:

我的文件名如下:

1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf

幸运的是,文件命名非常一致,但我不能绝对保证有人没有在他们应该使用下划线的地方使用空格。

考虑到这一点,我想解析字符串并提取以下详细信息:

$project_no = '1234
$series_no = '56
$sheet_no = '78'
$revision = 'D'
$title = 'A Fairly Short Title' 

目前,我使用以下方法获取此信息:

$filename = $_FILES['file']['name'][$i];
$filename = preg_replace('/\\.[^.\\s]{3,4}$/', '', $filename);
$parts = preg_split( "(_| )", $filename );
$project_no = $parts[0];
$series_no = $parts[1];
$sheet_no = $parts[2];
$revision = end($parts);

$title 只是删除$parts[0] $parts[1]$parts[2]end($parts) 后剩下的所有内容,但我应该如何表达呢?

我认为我可以使用

$title = implode(' ',\array_diff_key($parts, [0,1,2,end($parts)]));

但这不会删除末尾的$revision 位...

$title = FLOOR AS PROPOSED D

我错过了什么,我是否不必要地过度复杂化?

【问题讨论】:

标签: php regex filenames text-parsing preg-split


【解决方案1】:

array_diff_key 查看两个数组的关键比较。 end() 只是移动数组的内部指针,实际上没有用,因为从它返回的值不能用于计算 2 个数组键之间的差异。

当前比较的行为如下

array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,'D'])

这看起来 关键 明智的:

   array_diff_key([0,1,2,3,4,5,6,7], [0,1,2,3])

因此,implode 的最终结果是 4,5,6,7 键值的串联。

要将第二个参数数组值作为键,可以使用array_flip将键作为值,将值作为键,表达式如下:

$title = implode(' ',\array_diff_key($parts, array_flip([0,1,2,count($parts)-1])));

演示: https://3v4l.org/J6b5r

【讨论】:

    【解决方案2】:

    我担心你过于复杂了。我认为单个 preg_match() 调用是解析字符串的最直接方法。

    看起来您从https://stackoverflow.com/a/2395905/2943403 中获取了正则表达式模式来修剪文件名中的扩展名;但是,当单个非正则表达式函数用于相同目的时,我建议使用正则表达式函数。

    pathinfo($filename', PATHINFO_FILENAME)
    

    现在扩展已经被删除,让我们继续解析。

    代码:(Demo)

    $filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
    preg_match('~([^ _]+)[ _]([^ _]+)[ _]([^ _]+)[ _](.+)[ _](\S)~', pathinfo($filename, PATHINFO_FILENAME), $m);
    
    var_export([
        'project_no' => $m[1],
        'series_no' => $m[2],
        'sheet_no' => $m[3],
        'title' => str_replace('_', ' ', $m[4]),
        'revision' => $m[5],
    ]);
    

    输出:

    array (
      'project_no' => '1234',
      'series_no' => '56',
      'sheet_no' => '78',
      'title' => 'A FAIRLY SHORT TITLE',
      'revision' => 'D',
    )
    

    如果您对使用preg_split() 很执着,那么该模式会变得非常简单,但还有一些工作要做。

    代码:(Demo)

    $filename = '1234_56_78 A_FAIRLY_SHORT_TITLE_D.pdf';
    $m = preg_split('~ |_~', pathinfo($filename, PATHINFO_FILENAME));
    $revision = array_pop($m);
    
    var_export([
        'project_no' => $m[0],
        'series_no' => $m[1],
        'sheet_no' => $m[2],
        'title' => implode(' ', array_slice($m, 3)),
        'revision' => $revision,
    ]);
    // same output as earlier snippet
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-20
      • 2013-05-23
      • 1970-01-01
      • 1970-01-01
      • 2012-10-16
      • 2016-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多