regex - PHP Custom command parser
Get the solution ↓↓↓Im making a telegram bot and its very hard to get input value from string. My goal is to make my command is easy to write and easy to understand. This is some example command i got from client message
,simpleImage. query Dark background. width 200. height 200. text %fortune_teller%
That should be an array like this
[simple_image][query] => 'Dark background'
[simple_image][width] => '200'
[simple_image][height] => '200'
[simple_image][text] => '%fortune_teller%'
and for empty argument should like this
,sayHello. %custom_id%
[say_hello] => '%custom_id%'
But i have some problem when i try input some japanese text and special character like\, *, &, |, et cetera
on
,cmd. cat files.txt 2>/dev/null && find $HOME -type f -iname \*.mp3 -delete
This is some code i write so far
<?php
function parse($string) {
preg_match_all("/,?([a-z_]+)?\..([a-z]+)\s([a-z\s%_]+)/", $string, $tmp);
$query = array_combine($tmp[2], $tmp[3]);
if(!empty($tmp[1])) {
return array_merge([$tmp[1][0]=>true], $query);
}
}
var_dump(parse($update['message']));
Answer
Solution:
I virtually never recommend named capture groups because they just bloat the pattern and the output array of matches, but for those who prefer them, you might use this:
~(?:^,(?<COMMANDS>[^.]+)|\G(?!^))\.(?= )(?: (?<KEYS>\S+))? (?<VALUES>.+?(?=\. |$))~
Otherwise:
~~(?:^,([^.]+)|\G(?!^))\.(?= )(?: (\S+))? (.+?(?=\. |$))~~
Effectively, you should use\G
(continue metacharacter) to continue matching a variable number of sequences after the leading command substring. My pattern relies on the fact that the command and subsequent key-value pairs are delimited by dots that are immediately followed by a space. If you cannot 100% rely on this delimiting sequence, then you need to resolve this issue before trying to move forward.
Once you have the matches array (Demo), you merely need to iterate it to build the desired output structure.
Code: (Demo)
$commands = [
',simpleImage. query Dark background. width 200. height 200. text %fortune_teller%',
',sayHello. %custom_id%',
',cmd. cat files.txt 2>/dev/null && find $HOME -type f -iname \*.mp3 -delete',
];
foreach ($commands as $command) {
$result = [];
if (preg_match_all('~(?:^,([^.]+)|\G(?!^))\.(?= )(?: (\S+))? (.+?(?=\. |$))~', $command, $out)) {
foreach ($out[2] as $index => $subKey) {
if (strlen($subKey)) {
$result[$out[1][0]][$subKey] = $out[3][$index];
} else {
$result[$out[1][0]] = $out[3][$index];
}
}
}
echo var_export($result, true) . "\n---\n";
}
Output:
array (
'simpleImage' =>
array (
'query' => 'Dark background',
'width' => '200',
'height' => '200',
'text' => '%fortune_teller%',
),
)
---
array (
'sayHello' => '%custom_id%',
)
---
array (
'cmd' =>
array (
'cat' => 'files.txt 2>/dev/null && find $HOME -type f -iname \\*.mp3 -delete',
),
)
---
Share solution ↓
Additional Information:
Link To Answer People are also looking for solutions of the problem: 403 this action is unauthorized.
Didn't find the answer?
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Similar questions
Find the answer in similar questions on our website.
Write quick answer
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.