get number from file with regexp? - php

I've got files named
1234_crob.jpg
1234.jpg
2323_örja.bmp
2323.bmp
etc.
How can I just retrieve numbers e.g. 1234 and 2323?

If the file names all start with numbers there is no need to use regular expressions, try this instead:
foreach (glob('/path/to/dir/{0,1,2,3,4,5,6,7,8,9}*', GLOB_BRACE) as $file)
{
echo $file . ' = ' . intval(basename($file)) . "<br />\n";
}
This updated glob pattern will only match filenames that start with a digit, as you requested.
#ghostdog74: You're right.
foreach (glob('/path/to/dir/{0,1,2,3,4,5,6,7,8,9}*', GLOB_BRACE) as $file)
{
echo $file . ' = ' . filter_var(basename($file), FILTER_SANITIZE_NUMBER_INT) . "<br />\n";
}

First explode on the period, and then explode on the underscore, and then your number is the first element in the returned list.
<?php
$str1 = "1234.jpg";
$str2 = "1234_crob.jpg";
$pieces = explode("_",current(explode(".",$str1)));
echo $pieces[0]; // prints 1234
$pieces = explode("_",current(explode(".",$str2)));
echo $pieces[0]; // prints 1234
?>
Yes, I realize this is not a regular expression, but this is too simple a task to use regular expressions.
EDIT: Modified code to work for your newly edited formatting examples.
EDIT: Modified to fit cleanly in one line of code.

Assuming you only pass in filenames (and not filepaths), the following should retrieve all consecutive numbers 0-9:
function getDigits($fn) {
$arr = array();
preg_match('/[0-9]+/', $fn, $arr);
return $arr;
}
EXAMPLE USAGE
var_dump(getDigits('hey_12345.gif'));
/*
output:
array(1) {
[0]=>
string(5) "12345"
}
*/
var_dump(getDigits('123487_dude.jpg'));
/*
output:
array(1) {
[0]=>
string(6) "123487"
}
*/

try this. If you have numbers like 045_test.jpg, using intval will give you 45 instead of 045
$path="/path/[0-9]*";
foreach (glob($path) as $files ){
$base=basename ($files);
$s = preg_split("/[^0-9]/",$base,2);
echo $s[0]."\n";
}

Related

Unexpected result using OR operator in regular expression

I've a problem with a regular expression. I have a text which is read from a file. The text can contain one or more IDs separated by comma.
And then I have a list of IDs and want to check if one of these IDs match with my text so I try to use an OR operator:
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/' . $idString . '/', $text)) {
echo 'yes' . PHP_EOL;
} else {
echo 'no' . PHP_EOL;
}
I'm expecting that nothing matches because the IDs 1453 and 2018 are not found in my lookup string but it matches. I think that's because the ID 3 matches with 1453 but this is not correct for my use case.
That's too easy to work around it using arrays. You shouldn't use Regular Expressions if you can work with them but it seems this is not your real problem but an MCVE for a different one.
You should use word boundaries \b otherwise a number like 4 is found in 1453. preg_match() third argument holds results to analyze what is going on.
preg_match('/\b(?:' . $idString . ')\b/', $text, $match)
The syntax for preg_match is ($pattern, $text). Change it as follows, worked for me.
<?php
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idString = str_replace(',', '|', $idString);
$text = '1453,2018';
if (preg_match('/(' . $text . ')/', $idString)) {
echo 'yes' . PHP_EOL;
} else {
echo 'no' . PHP_EOL;
}
?>
You can see what gets matched by your Regex by outputting the matches, eg:
if (preg_match('/' . $idString . '/', $text, $matches)) {
echo 'yes' . PHP_EOL;
print_r($matches);
} else {
echo 'no' . PHP_EOL;
}
You'd have to adapt your regex to match against whole words only... for example like this:
if (preg_match('/\b(' . $idString . ')\b/', $text)) {
https://regex101.com/r/M1Pieb/2/
Or you could avoid using regex altogether (recommended, its getting a bit crazy..) by using explode
$idString = '2561,3,261,6,540,33,3105,2085,38,42,1066,49,3377,53,3161,91,356,3179,3695,3184,370,123,3451,124,3710,2188,141,404,1435,160,1443,432,435,440,1721,3261,2498,205,3282,476,482,3301,486,749,3309,243,3059,759,2046,4,262,785,534,541,3360,34,3106,2086,39,43,50,3378,54,1337,61,1351,3157,3162,360,3696,3185,631,3450,3200,666,1436,673,1444,3748,3262,2499,206,3279,3283,470,477,483,3302,490,755,760,2047,2562,1029,263,23,542,35,3107,2087,40,552,553,1321,47,51,3379,55,1338,3163,361,3697,3186,633,3452,639,143,3223,1445,3749,1450,3263,2500,207,3284,478,484,3303,2559,264,1297,22,543,36,44,57,1339,3389,62,3164,3677,362,3180,634,144,1685,1446,430,700,208,3286,479,1249,485,3306,2558,255,265,524,30,288,46,2095,63,2375,3165,403,1447,3242,696,1724,3557,3304,1770,3066,2563,266,544,2338,555,3131,3166,2204,415,1448,1239,3288,480,3305,754,267,545,3370,2378,3152,3170,648,147,679,1449,2537,753,2546,505,2564,3335,268,535,537,539,546,549,65,69,3167,148,3244,744,3068,2565,269,286,547,292,1334,1340,3659,3168,383,153,1705,3267,3060,2566,270,271,3099,548,1660,398,154,1706,2511,746,3332,2568,272,3148,422,3269,752,768,273,3381,3153,3199,155,468,784,274,3093,325,1657,3319,510,3329,3333,275,1432,2230,441,1722,773,3338,276,3641,2108,491,3339,277,2398,107,3181,2245,757,3346,2100,619,1760,2050,3351,2103,667,19,3372,2534,1064,351,1726,2394,2508,2538,2104,3147,2083,2097,2042,2096,2165,2049,2525,2526,1774,2392,2080,2043,2542,2547,2129,2540,2536,2190,2226,2569,2572,2373,2507';
$idStrings = explode(',', $idString);
$values = ['1453', '2018'];
$matchedValue = null;
foreach ($values as $value) {
if (in_array($value, $idStrings)) {
$matchedValue = $value;
break;
}
}
if ($matchedValue !== null) {
echo 'yes: ' . $matchedValue;
} else {
echo 'no';
}

PHP - Exploding each item in an array created by explode

My code is...
$string ="foo:bar,bar,bar|foo2:bar2,bar2,bar2";
$first_array = explode("|", $string);
function split(&$block) {
$block = explode(":", $block);
}
array_walk($first_array, "split");
echo $block["0"]["0"];
echo "<br />";
echo $block["0"]["1"];
?>
Thank you for the help thus far. From what I've gathered this should be the clean version of the supplied code. This does not echo anything, and neither does the code supplied.
This will do the trick:
$string ="foo:bar:bar:bar|foo2:bar2:bar2:bar2";
// first explode on |
$first_array = explode("|", $string);
// this function go on each lines of an array and transform each by a function
array_walk($first_array, function(&$item) {
// so for each line explode with ':' as delimiter
$item = explode(':', $item);
});
// To check all lines of the array
foreach($first_array as $line_array) {
//my code for each sub-array
}
// To get only the last (second)
$second_sub = array_pop($first_array);
// if you want one dimension with all exploded you can use
// this function split with a regexp pattern
// "/[\|:,]+/" foreach "|" or ":" or "," split the string
preg_split("/[\|:,]+/", $string);
Don't use $block since it's defined in another scope, moreover you cannot give "split" as a name for your function since it's an existing php function
$string ="foo:bar,bar,bar|foo2:bar2,bar2,bar2";
$first_array = explode("|", $string);
function mysplit(&$block) {
$block = explode(":", $block);
}
array_walk($first_array, "mysplit");
echo $first_array[0][0];
echo "<br />";
echo $first_array[0][1];

Retrieve text from XML?

I want to get all words between XML tags from a array and the current outcome is:
Notice: Array to string conversion in ........ on line 84
Result is: Array
if(isset($_POST['send']))
{
echo "sync is started <br>";
$handle = fopen("XML/$file_name", "r");
if ($handle)
{
while (($line = fgets($handle)) !== false)
{
$keywords=array("series_title","series_type","series_episodes");
for ($i=0; $i < 3; $i++)
{
$pattern = "/<$keywords[$i]>(.*?)<\/keywords[$i]>/";
preg_match($pattern, $line, $matches);
echo "result is: " . $matches . "<br>";
}
}
}
else
{
$upload_text = "error";
}
$upload_text ="finished";
fclose($handle);
//unlink('XML/' . $file_name);
}
You should use SimpleXML to read the XML instead. Here is an example:
<?php
$string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<myanimelist>
<anime>
<series_animedb_id>1143</series_animedb_id>
<series_title><![CDATA[.hack//Intermezzo]]></series_title>
<series_type>Special</series_type>
<series_episodes>1</series_episodes>
</anime>
<anime>
<series_animedb_id>299</series_animedb_id>
<series_title><![CDATA[.hack//Liminality]]></series_title>
<series_type>OVA</series_type>
<series_episodes>4</series_episodes>
</anime>
</myanimelist>
XML;
$result = simplexml_load_string($string);
foreach ($result->anime as $anime)
{
echo trim($anime->series_title), "\n";
echo $anime->series_type, "\n";
echo $anime->series_episodes, "\n";
echo "==========================\n\n";
}
Live DEMO.
In your case you would use simplexml_load_file, so your code would look like this:
<?php
$result = simplexml_load_file('your_file_path_here.xml');
foreach ($result->anime as $anime)
{
echo trim($anime->series_title), "\n";
echo $anime->series_type, "\n";
echo $anime->series_episodes, "\n";
}
Well, as you can read in the Official PHP Documentation, the optional preg_match third argument will be an array
matches
If matches is provided, then it is filled with the results of search.
$matches[0] will contain the text that matched the full pattern,
$matches1 will have the text that matched the first captured
parenthesized subpattern, and so on.
So simply change your :
echo "result is: " . $matches . "<br>";
to :
echo "result is: " . $matches[1] . "<br>";
Hope it helps
The value returned in the $matches parameter of the preg_match function is an array, the first element of which is the entire match, and the following elements are the capture groups (the parts between parentheses).
So, in your code, you'd only be interested in $matches[1]:
echo "result is: $matches[1]<br>";

Identify a blank line in a text area

I am trying to identify a blank lines in a string. Below is my attempt in PHP:
<?php
$alldevs = $_POST['devs'];
$devices = explode("\n", $alldevs);
foreach($devices as $device) {
if(!empty($device)){
echo $device;
} else {
echo "end of value";
}
}
?>
When I input the following:
1
2
3
4
I get this output:
1
2
3
4
But what it should be outputting is this:
1
2
3
end of value
end of value
4
What am I doing wrong?
They probably contain a \r (which is posted on new lines in text areas for some browsers/OS'es), a space or a tab character. You can get rid of these by using the trim() command:
<?php
$alldevs = $_POST['devs'];
$devices = explode("\n", $alldevs);
foreach ($devices as $device) {
$device = trim($device); //Trim that string!
if(!empty($device))
{
echo $device;
}
else
{
echo "end of value";
}
}
?>
Oh, and PLEASE indent your code for your own and everybody elses sake.
Alternatively, split up your string by using regex:
$devices = preg_split("/(\r\n|\n\r|\r|\n)/", $alldevs);
This should give you what you want:
if( trim($device) !== '' )
{
echo $device."<br>";
}
else
{
echo "end of value"."<br>";
}
Outputs:
1
2
3
end of value
4
I think your problem is with \r\n
Use this code
$alldevs = str_replace("\r", '', $alldevs);
Then explode it, and also use trim for clean spaces
$alldevs = trim($alldevs);
first, please read dealing with line endings and wikipedia newline
second, you are using string explode when you should use a function like preg_match_all
code should look something like this (mind the bad regex please):
<?php
$string = $_POST['devs'];
preg_match_all('%^([^\n\r]*)[\n\r]?$%im', $string, $matches);
foreach ($matches[1] as $match) {
if($match) {
var_dump($match);
} else {
echo 'empty line' . PHP_EOL;
}
}
adjust this code to fit your needs, i left a var_dump there so you could see the string length.
Add a check for a string with more than 0 characters,
if(!empty($device) && strlen($device)>0) {
I would also try a use case with \r\n on your line-breaks, you'll run into that as well.
you can try this
$devices = preg_replace('/^\s*$/','end of value',explode("\n",$alldevs));
foreach($devices as $device) {
echo $device, "\n";
}

annoying array tags.. want a pretty output

What i'm trying to do is make my output usable for a spreadsheet.
I want each item in the output without array tags or not mashed together but starting with an asterisk and ending with a % sign.
<?php
$file = file_get_contents('aaa.txt'); //get file to string
$row_array = explode("\n",$file); //cut string to rows by new line
$row_array = array_count_values(array_filter($row_array));
foreach ($row_array as $key=>$counts) {
if ($counts==1)
$no_duplicates[] = $key;
}
//do what You want
echo '<pre>';
print_r($no_duplicates);
//write to file. If file don't exist. Create it
file_put_contents('no_duplicates.txt',$no_duplicates);
?>
Maybe this would give you what you want:
$str = "*" . implode("% *", $no_duplicates) . "%";
echo '<pre>';
echo $str;
echo '</pre>';

Categories