PHP 解析 .ini 文件问题与换行符/需要正则表达式?

标签 php regex parsing ini

我在解析 .ini 文件时遇到了一些问题,这些文件的值没有用引号括起来,并且其中有一些换行符。这是一个例子:

[Section1]
ID=xyz

# A comment
Foo=BAR

Description=Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
 quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
 consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
 cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
 proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Screenshot=url-goes-here.png
Categories=some,categories

Vendor=abc

[Section2]
Description=Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
 quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
 consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
 cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
 proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

 Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,

 quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
 consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
 cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
 proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Somekey=somevalue

当我尝试使用 parse_ini_string($file_content, true, INI_SCANNER_RAW); 解析此字符串时,它返回 false 或仅返回 Description 的第一行。例如

["Description"]=> "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod" // next lines are missing

我已经尝试删除换行符并将值括在引号中,但找不到有效的正则表达式。我需要一个匹配每个键/值的模式,直到下一个键/值或直到评论开始。

不幸的是,有时键在空行之后开始,有时不是。值中可以有空行(查看 Section2 中的 Description)。

所以问题是,我如何修改/清理这个字符串,使其可以用 parse_ini_string 读取?

最佳答案

您可以使用此模式描述多行键/值:

/^\w+=\N*(?:\R++(?!\w+=|[[#;])\N+)+/m

INI_SCANNER_NORMAL 默认选项允许在引号之间包含多行值,因此您只需添加引号即可:

$content = preg_replace('~^\w+=\K\N*(?:\R++(?!\w+=|[[#;])\N+)+~m', '"$0"', $content);

图案细节:

~                  # pattern delimiter
^                  # start of the line
\w+                # key name
=
\K                 # discards characters on the left from the match result
\N*                # zero or more characters except newlines
(?:                # non-capturing group: eventual empty lines until a non empty line
    \R++           # one or more newlines
    (?!\w+=|[[#;]) # not followed by another key/value, a section or a comment
    \N+            # one or more characters except newlines
)+                 # at least one occurence
~m                 # switch on the multiline mode, ^ means "start of the line"

此模式仅针对多行值,其他值不加引号。

注意:我假设每个键、注释、部分都从一行的开头开始。如果前导空格不是这种情况,您可以轻松调整模式,在每个换行符后添加 \h*+

如果一行中的任何地方都允许注释,请将 \N 更改为 [^#\r\n]


如果您想使用 INI_SCANNER_RAW 选项,您必须删除值中的换行符:

$pattern = '~(?:\G(?!\A)|^\w+=[^#\r\n]*)\K\R++(?!\w+=|[[#])([^#\r\n]+)~';
$content = preg_replace($pattern, ' $1', $content);

该模式逐个匹配一组连续的换行符后跟一个非空行,并将连续的换行符替换为空格。

另一种方法是使用第一个模式,但这次使用 preg_replace_callback 在回调函数中执行简单的字符转换。请注意,如果您想转义特殊或有问题的字符,这种方式可能会很有趣。

关于PHP 解析 .ini 文件问题与换行符/需要正则表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31404066/

相关文章:

python - Pyparsing:如何实现C风格注释的特殊处理?

java - 从 Android 网站解析

java - 使用 simpledateformat 进行日期解析

php - 使用 PHP SimpleTest 进行测试

php - MySql:在子查询中引用父查询获取的数组

php - 安全地将数据插入 MySQL 表并打印

javascript - 用于字母数字字符和数字范围组合的正则表达式

php - 无法在 Centos 上安装 php-ZendFramework-Db-Adapter-Pdo-Mysql

java - 检查字符串中的非数字字符

python正则表达式重复模式匹配整个字符串