PHP-php 正则应用 处理特殊格式文本

PHP-php 正则应用 处理特殊格式文本

浮生未歇 发布于 2017-07-03 字数 222 浏览 1167 回复 1

现有 如下格式的文本,要求解析出不同的片段

parts: [
newline
| "===" section
| "---" subsect
| "!" note
| example
| paragraph
]

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清晨说ぺ晚安 2017-10-10 1 楼

这个问题的文法不完整,补充一下:

parts: [
  newline
| "{" package start
| "}" package end
| "===" section
| "---" subsect
| "!" note
| example
| paragraph
]

如果只是以空行+换行分割+前导字符匹配的方式处理这种结构化数据,应该不是这个问题的难点,我想难点应该是:如何区分 paragraph 和 example,问题描述里面没有明确说明区别,我个人观察了一下,发现区别如下:

  • paragraph:第一段的第一个单词的首字母大写
  • example:第一段的第一个单词的首字母小写 或 全大写

另外,配合空行来判断该段是不是example即可。至于输出成什么数据结构,这不是难点,重点在解析和区分 example|paragraph

$file = 'txt.php';

$preIdent = array(
    '{' => 'package',
    '===' => 'section',
    '---' => 'subject',
    '!' => 'note',
    '}' => false
);

$fullIdent = array(
    '/^[A-Z][a-z]+/' => 'paragraph',
    '/^([A-Z]+|[a-z]+)/' => 'example',
);

$curType = null;    //记录当前代表的段落类别
$result = array();  //结果数组
$curValue = null;
foreach(file($file) as $line){
    $line = trim($line);
    if(empty($line)){
        $curType = null;
        continue;
    }
    if($curType === null){
        $curType = getTypeByLine($line);
        if($curType === false){
            $curType = null;
            continue;
        }
        if($curValue !== null){
            $result[] = $curValue;
        }
        $curValue = array(
            'type' => $curType,
            'value' => ''
        );
    }
    $curValue['value'] .= getDataByLine($curType, $line);
}

if($curValue !== null){
    $result[] = $curValue;
}

print_r($result);

function getTypeByLine($line){
    global $preIdent, $fullIdent;
    foreach($preIdent as $r => $s){
        if(strpos($line, $r) === 0){
            return $s;
        }
    }
    foreach($fullIdent as $r => $s){
        if(preg_match($r, $line)){
            return $s;
        }
    }
    return 'paragraph';
}

function getDataByLine($s, $line){
    global $preIdent, $fullIdent;
    if(in_array($s, $preIdent)){
        foreach($preIdent as $k => $ss){
            if($s == $ss){
                break;
            }
        }
        //@preg_match($k, $line, $m);
        return substr($line, strlen($k));
        //return $m[1];
    }
    return $line;
}