PHP Regex search failing when adding a second capture group - php

I have the following named capture group that works exactly as intended. It grabs the last date/time of a specific format from a string of text.
$re = "/.*(?<date>[0-9]+\\/[0-9]+\\/[0-9]+ [0-9]+:[0-9]+:[0-9]{1,2} (AM|PM))/s";
I want to capture the user ID that follows so I changed it to the following
$re = "/.*(?<date>[0-9]+\\/[0-9]+\\/[0-9]+ [0-9]+:[0-9]+:[0-9]{1,2} (AM|PM)) (?<name>\\w+)/s";
However when I do so it breaks both values giving the following error
Notice: Undefined index: date in Q:\XAMPP\htdocs\index.php on line 272
The Error stems from the preg_match matches array being blank. Print_r confirms the array does not contain any information once the regex is changed to the second value.
Both of these work fine in external sites as the link below to Regex101 shows
http://regex101.com/r/zO0mK0/4
Using PHP 5.5.9
So the question is, am I missing something in this regex statement that is breaking it between the external site and my internal code or does this work meaning it is 100% purely my php that is causing this issue.
$LastDateRegex = "/.*(?<date>[0-9]+\\/[0-9]+\\/[0-9]+ [0-9]+:[0-9]+:[0-9]{1,2} (AM|PM))/s";
preg_match($LastDateRegex, $arr2['WorkLog'], $LastDateMatches);
$Modsecs = (strtotime($ts) - strtotime($LastDateMatches['date']))%60;
This is an example of the code being used. As mentioned above, I know the error stems from the $LastDateMatches array being empty for the second regex example, however the code works 100% with the first so there is something between the two that causes the issue.

You have an extra \ here: \\w+ and \\ at a few places, if that makes a difference?
Not quite sure what you want returned but runnning this regular expression, where $str is the text you have in your regex101-link,
$regex = "/.*(?<date>\d+\/\d+\/\d+ \d+:\d+:\d{1,2} (?:AM|PM)) (?<name>\w+)/s";
preg_match($regex, $str, $LastDateMatches);
Output,
Array
(
[0] => ...
[date] => 6/20/2014 10:04:32 PM
[1] => 6/20/2014 10:04:32 PM
[name] => ihugett
[2] => ihugett
)

Related

TextArea joins as one string to PHP how can I set the other strings in new line with help of delimiter

I've tried searching all over google and tried a similar problem and answers yet I still didn't get my problem done.
So basically, I'm making an HTML to write user input in a textbox which is the user would input:
Dog,
cat,
coronavirus,
Fever,
Cough,
Then into my PHP code, I capture it with:
$input = $_GET['contents'];
So I tried this one which I saw from googling and it doesn't have an explanation but logically its about array:
$input= explode(array(",", ""), $input)[0];
It works but the problem is that it only shows the first output which is:
Dog
Dog
Dog
Dog
Dog
But when I tried to remove the delimiter code, it shows one string only:
Dog,cat,coronavirus,Fever,Cough,
I thought about it something related to array but I'm not sure, is there any way to display all of them per line and with the help with delimiter?
UPDATE:
So I tried doing print_r($secs); and it shows like this:
Array ( [0] => Dog [1] => cat )
Array ( [0] => )
My accomplishment is to read all of the arrays one by one in another line instead of joining it as one strings. Sorry for bad english and im trying my best to explain.
you do not need the array() line.
Instead
if(strpos($_GET['contents'],',') !== false) { //check for commas first
$input = explode(',' , $_GET['contents']);
echo '<pre>';
print_r($input); //gives you the array
echo '</pre>';
}
to access each string individually, call the offset. For example, print_r($input[0]);
Also a friendly piece of advice. You seem like a beginner. You do not have to execute multiple commands in one line. Write your code step by step.

getCsvControl() always returns same delimiter - PHP

$file = new SplFileObject('D:\BackUp\addressbook.csv');
print_r($file->getCsvControl());
What i am trying to do is find the delimiter of a csv file using php. the addressbook.csv file looks like
"id";"firstname";"lastname";"phone";"email"
"1";"jishan";"ishrak";"17878";"jishan.ishrak#gmail.com"
and another file is addressbook1.csv which is like
"id","firstname","lastname","phone","email"
"1","jishan","ishrak","17878","jishan.ishrak#gmail.com"
one is separated by "," and another one is with ";" but the function
getCsvControl()
always returns an array like
Array ( [0] => , [1] => " )
I mean in the [0] index it always gives "," for both files
is there a way to solve this issue.
This is not a bug. SplFileObject::getCsvControl() is never intended to detect the delimiter from a CSV file. It returns only the default control characters or the one previously set with SplFileObject::setCsvControl(). And this set CSV control characters are used, if is nothing handed over in the SplFileObject::fgetcsv() method.
Ok, it's badly documented, but this were my first thoughts, the method would never detect the characters and a look into the php source code confirmed this.
Proabably this is a bug?
as you can see here php doc 1st comment 1 year ago - Seems that this function always returns the same delimiter.
UPDATE
this is not a bug look at Pazi ツ answer.

php sscanf doesnt parse string properly

I develop ADIF parser and parsing process comes to the point where I use sscanf() php function The strind that I parse is as following: "QSO_DATE:8:D>20070909" and I need to draw info from here as following: "QSO_DATE", "8", "20070909" so I use code:
sscanf("QSO_DATE:8:D>20070909", "%s:%d:D>%d")
But returning array looks like this:
Array
(
[0] => QSO_DATE:8:D>20070909
[1] =>
[2] =>
)
What is wrong? maybe there is more efficient way to parse bunch of records like these:
<CALL:7>EM200FT<QSO_DATE:8:D>20140324<TIME_ON:4>1657<BAND:3>12M<MODE:5>PSK63<RST_SENT:3>599<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<APP_EQSL_AG:1>Y<GRIDSQUARE:6>KN45kj<EOR>
<CALL:5>9V1SV<QSO_DATE:8:D>20140328<TIME_ON:4>1019<BAND:3>10M<MODE:4>JT65<RST_SENT:6>VK4CMV<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:54>Thank you and I confirm your SWL report, 73's de Siva.<APP_EQSL_AG:1>Y<GRIDSQUARE:6>OJ11ui<EOR>
<CALL:5>RA6DQ<QSO_DATE:8:D>20140328<TIME_ON:4>1019<BAND:3>10M<MODE:4>JT65<RST_SENT:3>599<RST_RCVD:0><QSL_SENT:1>Y<QSL_SENT_VIA:1>E<QSLMSG:3>73!<APP_EQSL_AG:1>Y<GRIDSQUARE:6>KN85nf<EOR>
%s means any characters, including colons, digits, chevrons, etc, except whitespace characters) and sscanf uses a greedy grab.... using more precise alternatives like %[A-Z_] or %[^:] might serve you better that %s
$result = sscanf("QSO_DATE:8:D>20070909", "%[^:]:%d:D>%d");
var_dump($result);
Which uses %[^:] to scan for any character other than a :

preg_match_all parsing, only one match

I have following input data(note that some of the whitespace is getting messed up):
aggr0_howzeg253_sata online raid_dp, aggr root, diskroot,
nosnap=off, raidtype=raid_dp,
32-bit raidsize=14, ignore_inconsistent=off,
snapmirrored=off, resyncsnaptime=60,
fs_size_fixed=off, snapshot_autodelete=on,
lost_write_protect=on, ha_policy=cfo,
hybrid_enabled=off, percent_snapshot_space=5%,
free_space_realloc=off
Volumes: root_vol_howzeg253, howzeg253_ixb_esx_vol16_sv_mirror,
howzeg253_ixb_esx_vol5_sv_mirror,
howzeg253_ixb_esx_vol18_sv_mirror,
howzeg253_ixb_esx_vol21_sv_mirror,
howzeg253_ixb_esx_vol33_sv_mirror,
howzeg253_ixb_esx_vol24_sv_mirror,
howzeg253_ixb_esx_vol34_sv_mirror
Plex /aggr0_howzeg253_sata/plex0: online, normal, active
RAID group /aggr0_howzeg253_sata/plex0/rg0: normal, block checksums
RAID group /aggr0_howzeg253_sata/plex0/rg1: normal, block checksums
aggr1_howzeg253_sata online raid_dp, aggr nosnap=off,
raidtype=raid_dp, raidsize=14,
32-bit ignore_inconsistent=off, snapmirrored=off,
resyncsnaptime=60, fs_size_fixed=off,
snapshot_autodelete=on, lost_write_protect=on,
ha_policy=cfo, hybrid_enabled=off,
percent_snapshot_space=5%,
free_space_realloc=off
Volumes: howzeg253_ixb_esx_vol6_sv_mirror,
howzeg253_ixb_esx_vol17_sv_mirror,
howzeg253_ixb_esx_vol7_sv_mirror,
howzeg253_ixb_esx_vol19_sv_mirror,
howzeg253_ixb_esx_vol23_sv_mirror,
howzeg253_ixb_esx_vol8_sv_mirror,
howzeg253_ixb_esx_vol36_sv_mirror
Plex /aggr1_howzeg253_sata/plex0: online, normal, active
RAID group /aggr1_howzeg253_sata/plex0/rg0: normal, block checksums
RAID group /aggr1_howzeg253_sata/plex0/rg1: normal, block checksums
I use this expression with preg_match_all:
preg_match_all("|(aggr[a-z0-9_]+)\s+.*Volumes.\s+(.*)\s+Plex.*checksums|s", $rawdata, $out);
However the output that I get only gives me the information from the first block(which seems parsed correctly; each block starts with aggr_... at the beginning of a line).
I tried different ways but couldn't get what I wanted(like multiline with the carrot at the beginning of the expression, and the s modifier).
So this is the output I get:
...
[1] => Array
(
[0] => aggr4_delng153_sas_sata
)
[2] => Array
(
[0] => delng153_ixb_esx_vol19, delng153_ixb_esx_vol20,
delng153_ixb_esx_vol21, delng153_ixb_esx_vol28,
delng153_ixb_esx_vol29, delng153_ixb_esx_vol30,
delng153_ixb_esx_vol31
)
I want the second block to be returned as well.
Can anyone help me out here?
Thanks in advance!
Try this:
preg_match_all("|(aggr[a-z0-9_]+)\s+.*Volumes.\s+(.*)\s+Plex.*checksums|sg", $rawdata, $out);
The global g search flag makes the RegExp search for a pattern throughout the whole string
Bro I think you are looking for this
'/(aggr[a-z0-9_]+)\s.*?Volumes:(.*?)rg1: normal, block checksums/s'
Really stupid that I yesterday evening couldn't find it.
This morning I looked 5 minutes and was like: no, will post it.
5 minutes later I found that with using modifier U it worked.
However I'll look into your proposed solutions as well.
It seems like Naveed's answer would return to much (block until the words "block cheksums") however I might be wrong.

Regex not finding all variables

I'm parsing some HTML, that I have generated in a form. This is a token system. I'm trying to get the information from the Regexp later on, but somehow, it's turning up only the first of the matches. I found a regexp on the Web, that did almost what I needed, except of being able to process multiple occurances.
I want to be able to replace the content found, with content that was generated from the found string.
So, here is my code:
$result = preg_replace_callback("/<\/?\w+((\s+(\w|\w[\w-]*\w)(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>\[\*.*\*\]\<\/[a]\>/i", array(get_class($this), 'embed_video'), $str);
public function embed_video($matches)
{
print_r($matches);
return $matches[1] . 'foo';
}
I really need only the attributes, since they containt all of the valuable information. The contents of the tag are used only to find the token. This is an example of what needs to happen:
<a type="TypeOfToken1" id="IdOfToken1">[*SomeTokenTitle1*]</a>
<a type="TypeOfToken2" id="IdOfToken2">[*SomeTokenTitle2*]</a>
After the preg_replace_callback() this should be returned:
type="TypeOfToken1" id="IdOfToken1" type="TypeOfToken2" id="IdOfToken2"
But, the callback function outputs the matches, but does not replace them with the return. So, the $result stays the same after the preg_replace_callback. What could be the problem?
An example with real data:
Input:
<p><a id="someToken1" rel="someToken1">[*someToken1*]</a> sdfsdf <a id="someToken2" rel="someToken2">[*someToken2*]</a></p>
returned $result:
id="someToken1" rel="someToken1"foo
Return from the print_r() if the callback function:
Array ( [0] => [*someToken1*] sdfsdf [*someToken2*] [1] => id="someToken1" rel="someToken1" [2] => rel="someToken1" [3] => rel [4] => ="someToken1" )
I think that it is not returning both of the strings it should.
For anyone else stumbling into a problem like this, try checking your regexp and it's modifiers.
Regarding the parsing of the document, I'm still doing it, just not HTML tags. I have instead gone with someting more textlike, that can be more easily parsed. In my case: [*TokeName::TokenDetails*].

Categories