<?php
function parse(string $input): array
{
static $pattern = <<<'EOD'
/
# 先頭
^
# name 部分
(?<name>
# \p{L}\p{N} を最低1個は含む
(?=[^「」\p{C}\p{L}\p{N}]*+[\p{L}\p{N}])
# カッコと制御文字以外の繰り返し
[^「」\p{C}]++
)?
# カッコ+空白だけのコメントの場合は読み飛ばす条件分岐
(?:
# empty_comment 部分
(?<empty_comment>
「
# カッコの中身
(?:
# empty_comment の再帰
(?&empty_comment)
)*+
」
)
# empty_comment がマッチしたらそこまでをすべて読み飛ばす
(*SKIP)(*FAIL)
|
# comment 部分
(?<comment>
「
# カッコの中身
(?:
# \p{L}\p{N} を最低1個は含む
(?=[^「」\p{C}\p{L}\p{N}]*+[\p{L}\p{N}])
# カッコと制御文字以外の繰り返し
[^「」\p{C}]*+
# または
|
# comment の再帰
(?&comment)
)*+
」
)?
)
# 末尾
$
/ux
EOD;
preg_match($pattern, $input, $match);
$name = $match['name'] ?? '';
$comment = $match['comment'] ?? '';
// 外側のカッコを切り取り
$comment = mb_substr($comment, 1, -1, 'UTF-8');
$name = $name === '' ? null : $name;
$comment = $comment === '' ? null : $comment;
return compact('name', 'comment');
}
$inputs = [
/*
* 正しい値が与えられた場合、一方か両方に値が入る
*----------------------------------------------*/
'一郎「こんにちは」', // ["name"=>"一郎","comment"=>"こんにちは"]
'二郎「男の中の「男」です」', // ["name"=>"二郎","comment"=>"男の中の「男」です"]
'三郎', // ["name"=>"三郎","comment"=>"null"]
'「こんばんは」', // ["name"=>"null","comment"=>"こんばんは"]
/*
* 不正な値が与えられた場合、いずれも null を返す
*----------------------------------------------*/
//(1)以下のように「」の後に文字がある場合 null とする
'「こんばんは」です', // ["name"=>"null","comment"=>"null"]
//(2)以下のように「」がセットじゃない場合 null とする
'五郎「男の中の「男」かも', // ["name"=>"null","comment"=>"null"]
'「男の中の「男」かも', // 同上
'「やばい', // 同上
'ねむい」', // 同上
'「', // 同上
'」', // 同上
'「「」', // 同上
//(3)以下のように記号だけの場合 null とする
'「」', // ["name"=>"null","comment"=>"null"]
'「「」」', // 同上
'「★」', // 同上
'「!!」', // 同上
];
foreach ($inputs as $input) {
var_dump([$input => parse($input)]);
}
- Output for 8.1.0 - 8.1.31, 8.2.10 - 8.2.27, 8.3.0 - 8.3.4, 8.3.6 - 8.3.15, 8.4.1 - 8.4.2
- array(1) {
["一郎「こんにちは」"]=>
array(2) {
["name"]=>
string(6) "一郎"
["comment"]=>
string(15) "こんにちは"
}
}
array(1) {
["二郎「男の中の「男」です」"]=>
array(2) {
["name"]=>
string(6) "二郎"
["comment"]=>
string(27) "男の中の「男」です"
}
}
array(1) {
["三郎"]=>
array(2) {
["name"]=>
string(6) "三郎"
["comment"]=>
NULL
}
}
array(1) {
["「こんばんは」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
string(15) "こんばんは"
}
}
array(1) {
["「こんばんは」です"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["五郎「男の中の「男」かも"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「男の中の「男」かも"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「やばい"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["ねむい」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「「」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「「」」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「★」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「!!」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
- Output for 8.3.5
- Warning: PHP Startup: Unable to load dynamic library 'sodium.so' (tried: /usr/lib/php/8.3.5/modules/sodium.so (libsodium.so.23: cannot open shared object file: No such file or directory), /usr/lib/php/8.3.5/modules/sodium.so.so (/usr/lib/php/8.3.5/modules/sodium.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
array(1) {
["一郎「こんにちは」"]=>
array(2) {
["name"]=>
string(6) "一郎"
["comment"]=>
string(15) "こんにちは"
}
}
array(1) {
["二郎「男の中の「男」です」"]=>
array(2) {
["name"]=>
string(6) "二郎"
["comment"]=>
string(27) "男の中の「男」です"
}
}
array(1) {
["三郎"]=>
array(2) {
["name"]=>
string(6) "三郎"
["comment"]=>
NULL
}
}
array(1) {
["「こんばんは」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
string(15) "こんばんは"
}
}
array(1) {
["「こんばんは」です"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["五郎「男の中の「男」かも"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「男の中の「男」かも"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「やばい"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["ねむい」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「「」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「「」」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「★」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
array(1) {
["「!!」"]=>
array(2) {
["name"]=>
NULL
["comment"]=>
NULL
}
}
preferences:
74.77 ms | 419 KiB | 5 Q