Regular Expression - PHP - php

I am using following PHP code
<?
$data = file_get_contents('http://www.kitco.com/texten/texten.html');
preg_match_all('/([A-Z]{3,5}\s+[0-9]{1,2},[0-9]{4}\s+([0-9.NA]{2,10}\s+){1,7})/si',$data,$result);
$records = array();
foreach($result[1] as $date) {
$temp = preg_split('/\s+/',$date);
$index = array_shift($temp);
$index.= array_shift($temp);
$records[$index] = implode(',',$temp);
}
print_R($records);
?>
To READ the following data
--------------------------------------------------------------------------------
London Fix GOLD SILVER PLATINUM PALLADIUM
AM PM AM PM AM PM
--------------------------------------------------------------------------------
Jun 03,2013 1396.75 1402.50 22.4300 1466.00 1487.00 749.00 755.00
May 31,2013 1410.25 1394.50 22.5700 1471.00 1459.00 755.00 744.00
--------------------------------------------------------------------------------
What i want to do is Read GOLD ( BID & ASK ) price from below table, can anyone help in the regular expression changes?
New York Spot Price
MARKET IS CLOSED
Will open in
----------------------------------------------------------------------
Metals Bid Ask Change Low High
----------------------------------------------------------------------
Gold 1411.20 1412.20 +22.90 +1.65% 1390.10 1418.00
Silver 22.74 22.84 +0.48 +2.13% 22.26 23.08
Platinum 1495.00 1501.00 +41.00 +2.82% 1470.00 1511.00
Palladium 756.00 761.00 +7.00 +0.93% 750.00 766.00
----------------------------------------------------------------------
Last Update on Jun 03, 2013 at 17:14.58
----------------------------------------------------------------------

I'm not sure you could modify your existing regex to match both tables easily, but if you had the second table in a string, you could use:
$string = "PLAIN TEXT TABLE DATA HERE";
preg_match('/Gold\s+(\d+\.\d{2})\s+(\d+\.\d{2})/',$string,$matches);
$goldBid = $matches[1];
$goldAsk = $matches[2];

Here I'm only matching the numbers and period character. This code should return the numbers you're looking for. It uses your data string from your example.
<?
preg_match_all('!Gold\s+([0-9.]+)\s+([0-9.]+)!i',$data,$matches);
//New York
$ny_bid = $matches[1][0];
$ny_ask = $matches[2][0];
print("NY\nbid: $ny_bid\n");
print("ask: $ny_ask\n\n");
//Asia
$asia_bid = $matches[1][1];
$asia_ask = $matches[2][1];
print("Asia\nbid: $asia_bid\n");
print("ask: $asia_ask\n");
?>
Output
NY
bid: 1411.20
ask: 1412.20
Asia
bid: 1406.80
ask: 1407.80

You can also use T-Regx library
<?php
pattern('Gold\s+([0-9.]+)\s+([0-9.]+)', 'i')->match($data)->forEach(function ($m) {
print 'bid: ' . $m->group(1);
print 'ask: ' . $m->group(2);
});

Related

Using preg_replace to reformat money amounts in text with PHP

I'm struggling with some regular expressions. What I want to do is find money amounts in a string, remove the €,$, or £ but keep the number, and then look to see if there is a 'b' or an 'm' - in which case write 'million platinum coins' or 'million gold coin' respectively but otherwise just put 'gold coins'.
I have most of that as a hack (see below) with the small problem that my regex does not seem to work. The money amount comes out unchanged.
Desired behaviour examples
I intend to leave the decimal places and thousands separators as is
$12.6m ==> 12.6 million gold coins
£2b ==> 2 million platinum coins
€99 ==> 99 gold coins
My code
Here is my non-working code (I suspect my regex might be wrong).
protected function funnymoney($text){
$text = preg_replace('/[€$£]*([0-9\.,]+)([mb])/i','\0 %\1%',$text);
$text = str_replace('%b%','million platnum coins',$text);
$text = str_replace('%m%','million gold coins',$text);
$text = str_replace('%%','gold coins',$text);
return $text;
}
I would greatly appreciate it if someone could explain to me what I am missing or getting wrong and guide me to the right answer. You may safely assume I know very little about regular expressions. I would like to understand why the solution works too if I can.
Using preg_replace_callback, you can do this in a single function call:
define ("re", '/[€$£]*(\.\d+|\d+(?:[.,]\d+)?)([mb]|)/i');
function funnymoney($text) {
return preg_replace_callback(re, function($m) {
return $m[1] .
($m[2] != "" ? " million" : "") . ($m[2] == "b" ? " platinum" : " gold") .
" coins";
}, $text);
}
// not call this function
echo funnymoney('$12.6m');
//=> "12.6 million gold coins"
echo funnymoney('£2b');
//=> "2 million platinum coins"
echo funnymoney('€99');
//=> "99 gold coins"
I am not sure how you intend to handle decimal places and thousands separators, so that part of my pattern may require adjustment. Beyond that, match the leading currency symbol (so that it is consumed/removed, then capture the numeric substring, then capture the optional trailing units (b or m).
Use a lookup array to translate the units to English. When the unit character is missing, apply the fallback value from the lookup array.
A lookup array will make your task easier to read and maintain.
Code: (Demo)
$str = '$1.1m
Foo
£2,2b
Bar
€99.9';
$lookup = [
'b' => 'million platinum coins',
'm' => 'million gold coins',
'' => 'gold coins',
];
echo preg_replace_callback(
'~[$£€](\d+(?:[.,]\d+)?)([bm]?)~iu',
function($m) use ($lookup) {
return "$m[1] " . $lookup[strtolower($m[2])];
},
$str
);
Output:
1.1 million gold coins
Foo
2,2 million platinum coins
Bar
99.9 gold coins
Your regex has a first full match on the string, and it goes on index 0 of the returning array, but it seems you just need the capturing groups.
$text = preg_replace('/[€$£]*([0-9\.,]+)([mb])/i','\1 %\2%',$text);
Funny question, btw!
Is this what you want?
<?php
/**
$12.6m ==> 12.6 million gold coins
£2b ==> 2 million platinum coins
€99 ==> 99 gold coins
*/
$str = <<<EOD
$12.6m
£2b
€99
EOD;
preg_match('/\$(.*?)m/', $str, $string1);
echo $string1[1] . " million gold coins \n";
preg_match('/\£(.*?)b/', $str, $string2);
echo $string2[1] . " million platinum coins \n";
preg_match('/\€([0-9])/', $str, $string3);
echo $string3[1] . " gold coins \n";
// output:
// 12.6 million gold coins
// 2 million platinum coins
// 9 gold coins

php regular expression parse data

I have a field which contain 20 character (pad string with space character from right) like below:
VINEYARD HAVEN MA
BOLIVAR TN
,
BOLIVAR, TN
NORTH TONAWANDA, NY
How can I use regular expression to parse and get data, the result I want will look like this:
[1] VINEYARD HAVEN [2] MA
[1] BOLIVAR [2] TN
[1] , or empty [2] , or empty
[1] BOLIVAR, or BOLIVAR [2] TN or ,TN
[1] NORTH TONAWANDA, or NORTH TONAWANDA [2] NY or ,NY
Currently I use this regex:
^(\D*)(?=[ ]\w{2}[ ]*)([ ]\w{2}[ ]*)
But it couldnot match the line:
,
Please help to adjust my regex so that I match all data above
What about this regex: ^(.*)[ ,](\w*)$ ? You can see working it here: http://regexr.com/3cno7.
Example usage:
<?php
$string = 'VINEYARD HAVEN MA
BOLIVAR TN
,
BOLIVAR, TN
NORTH TONAWANDA, NY';
$lines = array_map('trim', explode("\n", $string));
$pattern = '/^(.*)[ ,](\w*)$/';
foreach ($lines as $line) {
$res = preg_match($pattern, $line, $matched);
print 'first: "' . $matched[1] . '", second: "' . $matched[2] . '"' . PHP_EOL;
}
It's probably possible to implement this in a regular expression (try /(.*)\b([A-Z][A-Z])$/ ), however if you don't know how to write the regular expression you'll never be able to debug it. Yes, its worth finding out as a learning exercise, but since we're talking about PHP here (which does have a mechanism for storing compiled REs and isn't often used for bulk data operations) I would use something like the following if I needed to solve the problem quickly and in maintainable code:
$str=trim($str);
if (preg_match("/\b[A-Z][A-Z]$/i", $str, $match)) {
$state=$match[0];
$town=trim(substr($str,0,-2)), " ,\t\n\r\0\x0B");
}

How to replace the first blank space, within a string, with a different character?

I have a text (.txt) file that contains text like this:
5 General
-10 Time Limits
-20 Scheduled Maintenance Checks
-30 Reserved
-40 Reserved
-50 Unscheduled Maintenance checks
6 DIMENSIONS and AREAS
7 LIFTING and SHORING
-00 General
-10 Jacking
-20 Shoring
8 LEVELING and WEIGHING
-00 General
-10 Weighing and Balancing
-20 Leveling
9 TOWING and TAXIING
-00 General
-10 Towing
-20 Taxiing
I want to replace the first space in each line with a comma (I'm trying to convert a txt file to a csv to prepare it for importing into a db). I started down the track of using strpos() function, but couldn't get my head around what to do next.
Bonus task: I also want a semi colon at the end of each line.
EDIT : Added actual data instead of sample data.
A simple preg_replace with limit will work:
$str = '5 Here is some text.';
echo preg_replace('/ /', ',', $str, 1);
// OUTPUT:
// 5,Here is some text.
With loop:
<?php
$str = array('5 Here is some text.', '5 Here is some text.','-10 Here is some text.','-20 Here is some text.','-30 Here is some text');
foreach ($str as $a) {
echo preg_replace('/ /', ',', $a, 1)."<br>";
}
// OUTPUT:
// 5,Here is some text.
// -10,Here is some text.
// -20,Here is some text.
// -30,Here is some text.
EDIT FOR YOUR NEW EDIT:
$str = "5 General
-10 Time Limits
-20 Scheduled Maintenance Checks
-30 Reserved
-40 Reserved
-50 Unscheduled Maintenance checks
6 DIMENSIONS and AREAS
7 LIFTING and SHORING
-00 General
-10 Jacking
-20 Shoring
8 LEVELING and WEIGHING
-00 General
-10 Weighing and Balancing
-20 Leveling
9 TOWING and TAXIING
-00 General
-10 Towing
-20 Taxiing";
$array = explode(PHP_EOL, $str);
foreach ($array as $a) {
echo preg_replace('/ /', ',', $a, 1)."<br>";
}
// OUTPUT:
/*
5,General
-10,Time Limits
-20,Scheduled Maintenance Checks
-30,Reserved
-40,Reserved
-50,Unscheduled Maintenance checks
6,DIMENSIONS and AREAS
7,LIFTING and SHORING
-00,General
-10,Jacking
-20,Shoring
8,LEVELING and WEIGHING
-00,General
-10,Weighing and Balancing
-20,Leveling
9,TOWING and TAXIING
-00,General
-10,Towing
-20,Taxiing
*/
You can use str_pos() and str_replace():
$csvData = array();
foreach (file("input.txt") as $line) {
$spacePos = str_pos($line, ' ');
$csvData[] = substr($line, 0, $spacePos) . ',' . substr($line, $spacePos + 1);
}
Or you can go to the more advanced preg_replace() to search and replace a pattern:
$csvData = array();
foreach (file("input.txt") as $line) {
$csvData[] = preg_replace('/^([^ ]+) /', '\1,', $line);
}

PHP line parsed into separate objects

I have a line of code in my wordpress widget that outputs from an RSS feed:
<?php echo $entry->title ?>
and when displayed it looks like:
$220,000 :: 504 Freemason St, Unit 2B, Norfolk VA, 23510
or
$274,900 :: 1268 Bells Road, Virginia Beach VA, 23454
What is the easiest way to break this up into different objects?
For example, I'd like to have the price, street name, and city state zip in different objects. The problem is that some of the addresses have unit numbers and it's complicating things. Below is an example of how I would like it to work:
<?php echo $entry->price ?>
<?php echo $entry->street ?>
<?php echo $entry->citystatezip ?>
$220,000
504 Freemason St, Unit 2B
Norfolk VA, 23510
or
$274,900
1268 Bells Road
Virginia Beach VA, 23454
Here is a very crude regex that seems able to parse your string. I'm not the best with regexes, but it seems to work.
/^(\$(?:\d{1,3},?)*) :: (\d* [\w\s,\d]*), ([\w\s]* \w{2}, \d{5})$/
Use this with preg_match; the 1st group is the price, the 2nd is the address, and 3rd is the city/state/zip.
Example:
<?php
$ptn = '/^(\$(?:\d{1,3},?)*) :: (\d* [\w\s,\d]*), ([\w\s]* \w{2}, \d{5})$/';
if(preg_match($ptn, $entry->title, $match) === 1){
$price = $match[1];
$street = $match[2];
$citystatezip = $match[3];
}
What you need is a regular expression , check http://php.net/manual/en/function.preg-match.php
Use f.e. array explode ( string $delimiter , string $string [, int $limit ] ) which will give you array with strings if you use correct delimiter
The code below will fill your $entry object as required:
$string = '$274,900 :: 1268 Bells Road, Virginia Beach VA, 23454';
$pricePart = explode('::', $string);
$addressPart = explode(',', $pricePart[1]);
$entry = new stdClass();
$entry->price = trim($pricePart[0]);
if ( count($addressPart) == 3 ) {
$entry->street = trim($addressPart[0]);
$entry->citystatezip = trim($addressPart[1]) . ', ' . trim($addressPart[2]);
} else {
$entry->street = trim($addressPart[0]) . ', ' . trim($addressPart[1]);
$entry->citystatezip = trim($addressPart[2]) . ', ' . trim($addressPart[3]);
}
Updated answer to handle the unit bit
Update: changed array names, I hate $array.. names.. even if its just a mockup
(Note: this code isn't the prettiest, but its ment to give a base to work on. It should be cleaned up and improved a bit)

Regex to extract timestamp from a text in PHP

I have the following bit of text (or some similar variation of it):
Recurring Event
First start: 2010-09-16 17:00:00 EDT
Duration: 4800
Event Status: confirmed
I need to select the timestamp of the "First Start" field and the duration.
Normally I would split the string at the colons, but since the timestamp contains them, it sort of becomes problematic. I'm not so good with regular expressions, but does anyone know one that will be able to select the two bits of data I need?
cheers,
Mike
Assuming the format stays this way you can search for ": ", i.e. a colon followed by a space. The string following this would be your data.
For a simple non-regex solution, find the first : with strpos($input, ":"), then the rest of the line will have the value.
$content = '
Recurring Event
First start: 2010-09-16 17:00:00 EDT
Duration: 4800
Event Status: confirmed
';
$contentArray = explode('EDT' , $content);
$head = trim($content[0]);
//$head will contain 'Recurring Event First start:2010-09-16 17:00:00 '
$headArray = explode(' ' , $head);
$timeStamp = trim(end($headArray)); //which will have 17:00:00
You can do:
if(preg_match('/First start: ([-\d :]+)/',$input,$m)) {
$timeStamp = trim($m[1]);
}else{
$timeStamp = '';
}
if(preg_match('/Duration: (\d+)/',$input,$m)) {
$duration = $m[1];
}else{
$duration = '';
}

Categories