I am atempting to extract the sort code and account number from a filename given that the first 6 figures represent the sort code and the last 8 figures represent the account number. An example of the filename would be:
./uploads/Santander/Statement_01020387654321.qif
What I have written does not seem to work, as I am new to regex maybe someone can explain how this should be done, or where I have gone wrong.
$sort = '';
$acno = '';
$ret = preg_match('/Statment_[0-9]{14}\.(csv|qif|qfx|ofx)$/', $file);
if ($ret)
{
if (ereg ('/_[0-9]{14}\./', $file, $regs))
{
$reg = $regs[count($regs)-1];
$sort = substr($reg, 1, 6);
$acno = substr($reg, 7, 8);
}
}
I'm sure somebody versed with regular expressions can help you out, but it's possible without as well. It may be the more attractive option in the long run, because it's easier to maintain.
$path = "./uploads/Santander/Statement_01020387654321.qif"
$filename = pathinfo($path, PATHINFO_BASENAME); // "Statement_01020387654321.qif"
$temp_array = explode("_", $filename);
$sortcode = substr($temp_array[1], 0, 6); // 010203
$account = substr($temp_array[1], 6, 8); // 7654321
Do it in the first step of matching:
$ret = preg_match('/Statement_([0-9]{6})([0-9]{8})\.(csv|qif|qfx|ofx)$/', $file, $matches);
And in $matches you have info about sort number, account number and extension.
tested
echo $file ='./uploads/Santander/Statement_01020387654321.qif';
$ret = preg_match('/Statement_(\d{6})(\d{8})\.(csv|qif|qfx|ofx)$/', $file, $matches);
echo "<pre>";
print_r($matches);
returns
Array
(
[0] => Statement_01020387654321.qif
[1] => 010203
[2] => 87654321
[3] => qif
)
I think you just spelled "Statement" wrong in your Regex
In your Regex its: "Statment" without an "e"
Related
I have SKU numbers imported from a CSV file into SQL DB.
Pattern look like:
55A_3
345W_1+04B_1
128T_2+167T_2+113T_8+115T_8
I am trying to move all the letters in front of the numbers.
like:
A55_3
W345_1+B04_1
T128_2+T167_2+T113_8+T115_8
My best idea how to do it was to search for 345W and so, and to replace it with W345 and so:
$sku = "345W_1+04B_1";
$B_range_num = range(0,400);
$B_range_let = range("A","Z");
then generating the find and replace arrays
$B_find =
$B_replace =
maybe just using str_replace??
$res = str_replace($B_find,$B_replace,$sku);
Result should be for all SKU numbers
W345_1+B04_1
Any ideas?
You can use preg_replace to do this job, looking for some digits, followed by a letters and one of an _ with digits, a + or end of string, and then swapping the order of the digits and letters:
$skus = array('55A_3',
'345W_1+04B_1',
'128T_2+167T_2+113T_8+115T_8',
'55A');
foreach ($skus as &$sku) {
$sku = preg_replace('/(\d+)([A-Z]+)(?=_\d+|\+|$)/', '$2$1', $sku);
}
print_r($skus);
Output:
Array
(
[0] => A55_3
[1] => W345_1+B04_1
[2] => T128_2+T167_2+T113_8+T115_8
[3] => A55
)
Demo on 3v4l.org
Here I defined a method with specific format with unlimited length.
$str = '128T_2+167T_2+113T_8+115T_8';
echo convertProductSku($str);
function convertProductSku($str) {
$arr = [];
$parts = explode('+', $str);
foreach ($parts as $part) {
list($first, $second) = array_pad(explode('_', $part), 2, null);
$letter = substr($first, -1);
$number = substr($first, 0, -1);
$arr[] = $letter . $number . ($second ? '_' . $second : '');
}
return implode('+', $arr);
}
How to check substrings in PHP by prefix or postfix.
For example, I have the search string named as $to_search as follows:
$to_search = "abcdef"
And three cases to check the if that is the substring in $to_search as follows:
$cases = ["abc def", "def", "deff", ... Other values ...];
Now I have to detect the first three cases using substr() function.
How can I detect the "abc def", "def", "deff" as substring of "abcdef" in PHP.
You might find the Levenshtein distance between the two words useful - it'll have a value of 1 for abc def. However your problem is not well defined - matching strings that are "similar" doesn't mean anything concrete.
Edit - If you set the deletion cost to 0 then this very closely models the problem you are proposing. Just check that the levenshtein distance is less than 1 for everything in the array.
This will find if any of the strings inside $cases are a substring of $to_search.
foreach($cases as $someString){
if(strpos($to_search, $someString) !== false){
// $someString is found inside $to_search
}
}
Only "def" is though as none of the other strings have much to do with each other.
Also on a side not; it is prefix and suffix not postfix.
To find any of the cases that either begin with or end with either the beginning or ending of the search string, I don't know of another way to do it than to just step through all of the possible beginning and ending combinations and check them. There's probably a better way to do this, but this should do it.
$to_search = "abcdef";
$cases = ["abc def", "def", "deff", "otherabc", "noabcmatch", "nodefmatch"];
$matches = array();
$len = strlen($to_search);
for ($i=1; $i <= $len; $i++) {
// get the beginning and end of the search string of length $i
$pre_post = array();
$pre_post[] = substr($to_search, 0, $i);
$pre_post[] = substr($to_search, -$i);
foreach ($cases as $case) {
// get the beginning and end of each case of length $i
$pre = substr($case, 0, $i);
$post = substr($case, -$i);
// check if any of them match
if (in_array($pre, $pre_post) || in_array($post, $pre_post)) {
// using the case as the array key for $matches will keep it distinct
$matches[$case] = true;
}
}
}
// use array_keys() to get the keys back to values
var_dump(array_keys($matches));
You can use array_filter function like this:
$cases = ["cake", "cakes", "flowers", "chocolate", "chocolates"];
$to_search = "chocolatecake";
$search = strtolower($to_search);
$arr = array_filter($cases, function($val) use ($search) { return
strpos( $search,
str_replace(' ', '', preg_replace('/s$/', '', strtolower($val))) ) !== FALSE; });
print_r($arr);
Output:
Array
(
[0] => cake
[1] => cakes
[3] => chocolate
[4] => chocolates
)
As you can it prints all the values you expected apart from deff which is not part of search string abcdef as I commented above.
Below script is shown search string in a text file, my text file has contents like:
60, 1, 1, 188, pdgje5566
60, 1, 1, 188, pdgje5565
if(!empty($extTxId)){
$searchfor = $extTxId;
$matches = array();
$handle = #fopen($file, "r");
if ($handle)
{
while (!feof($handle))
{
$buffer = fgets($handle);
if(strpos($buffer, $searchfor) !== FALSE)
$matches[] = $buffer;
}
fclose($handle);
}
print_r($matches);
it output as
Array ( [0] => 60, 1, 1, 188, ppje5566 )
however i want to explode the data which is separate by comma(,) and store into variable, is that anyway to do it?
thanks.
i want to explode the data which is separate by comma(,)
Use explode().
If this is a CSV file (or some other delimited file), I suggest looking at fgetcsv(). It is effectively fgets() and explode(), which seems to be what you need.
Since you have spaces between each comma, you can trim each element.
// Iterate through each item int the array (you can do $matches[0] if you just want the first)
foreach ($matches as $match)
{
$output_array = array_map('trim',explode(',',$match));
print_r($output_array);
}
Output:
Array
(
[0] => 60
[1] => 1
[2] => 1
[3] => 188
[4] => pdgje5565
)
Example: http://codepad.org/aSyVX5Bj
Try like
foreach(Array[0] as $element)
{
echo $element;
}
If you know the exact structure of the input you're getting, you could do something like:
$string = '60, 1, 1, 188, pdgje5565';
// Using trim just to be sure
list($varA, $varB, $varC, $varD, $varE) = explode(', ', trim($string));
This way you would get the results as follows:
$varA = 60;
$varB = 1;
$varC = 1;
$varD = 188;
$varE = 'pdgje5565';
The main advantage here is you would get decent variables instead of array with abstract indexes, but it is only good if you're sure about you're structure being constant.
I need to turn this phone number:
5555555555
into this string with delimiters:
"555.555.5555"
Here's my code:
$phone = 5555555555;
$phoneArray = explode(2, $phone);
print_r($phoneArray);
and it returns this:
Array ( [0] => 555 [1] => [2] => 55555 )
What am I doing wrong?
Lots of ways to do this, and RegEx not required, but here's a nice and easy one w/ RegEx:
$phone = '5555555555';
echo preg_replace('/(\d{3})(\d{3})(\d{4})/', "$1.$2.$3", $phone);
Cheers
You need something more like this:
$number = '123456789';
$segments = array();
$segments[] = substr($number, 0, 3);
$segments[] = substr($number, 3, 3);
$segments[] = substr($number, 6, 4);
$number = implode('.', $segments); // Comes out to 123.456.7890
Note that you'll want to do some format checking first. You'll need to verify
that they actually entered a 10-digit number with no dividing symbols.
You probably don't want to use explode since you don't have a known delimiter within the string to cause the split. You could use str_split($phone,3) which would give you 3 array elements of 3, and a 4th of 1. Keep the first two and merge the final two together into your 3rd array elemnent:
$phone = 5555555555;
$phoneArray = str_split($phone,3);
$phoneArray[2] .= phoneArray[3];
print_r($phoneArray);
Hope that helps.
Assume I have the following string:
I have | been very busy lately and need to go | to bed early
By splitting on "|", you get:
$arr = array(
[0] => I have
[1] => been very busy lately and need to go
[2] => to bed early
)
The first split is after 2 words, and the second split 8 words after that. The positions after how many words to split will be stored: array(2, 8, 3). Then, the string is imploded to be passed on to a custom string tagger:
tag_string('I have been very busy lately and need to go to bed early');
I don't know what the output of tag_string will be exactly, except that the total words will remain the same. Examples of output would be:
I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p
I-ee have been-vb very busy-df lately-nn and need-f to go to bed-uu early-yy
This will lengthen the string by an unknown number of characters. I have no control over tag_string. What I know is (1) the number of words will be the same as before and (2) the array was split after 2, and thereafter after 8 words, respectively. I now need a solution explode the tagged string into the same array as before:
$string = "I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p"
function split_string_again() {
// split after 2nd, and thereafter after 8th word
}
With output:
$arr = array(
[0] => I have-nn
[1] => been-vb very-vb busy lately and-rr need to-r go
[2] => to bed early-p
)
So to be clear (I wasn't before): I cannot split by remembering the strpos, because strpos before and after the string went through the tagger, aren't the same. I need to count the number of words. I hope I have made myself more clear :)
You wouldn't want to count the number of words, you would want to count the string length (strlen). If it is the same string without the pipes, then you want to split it with substr after a certain amount.
$strCounts = array();
foreach ($arr as $item) {
$strCounts[] = strlen($item);
}
// Later on.
$arr = array();
$i = 0;
foreach ($strCounts as $count) {
$arr[] = substr($string, $i, $count);
$i += $count; // increment the start position by the length
}
I have not tested this, simply a "theory" and probably has some kinks to work out. There may be a better way to go about it, I just don't know it.
Interesting question, although I think the rope data structure still applies it might be a little overkill since word placement won't change. Here is my solution:
$str = "I have | been very busy lately and need to go | to bed early";
function get_breaks($str)
{
$breaks = array();
$arr = explode("|", $str);
foreach($arr as $val)
{
$breaks[] = str_word_count($val);
}
return $breaks;
}
$breaks = get_breaks($str);
echo "<pre>" . print_r($breaks, 1) . "</pre>";
$str = str_replace("|", "", $str);
function rebreak($str, $breaks)
{
$return = array();
$old_break = 0;
$arr = str_word_count($str, 1);
foreach($breaks as $break)
{
$return[] = implode(" ", array_slice($arr, $old_break, $break));
$old_break += $break;
}
return $return;
}
echo "<pre>" . print_r(rebreak($str, $breaks), 1) . "</pre>";
echo "<pre>" . print_r(rebreak("I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p", $breaks), 1) . "</pre>";
Let me know if you have any questions, but it is pretty self explanatory. There are definitely ways to improve this as well.
I'm not quite sure I understood what you actually wanted to achieve. But here are a couple of things that might help you:
str_word_count() counts the number of words in a string. preg_match_all('/\p{L}[\p{L}\p{Mn}\p{Pd}\x{2019}]*/u', $string, $foo); does pretty much the same, but on UTF-8 strings.
strpos() finds the first occurrence of a string within another. You could easily find the positions of all | with this:
$pos = -1;
$positions = array();
while (($pos = strpos($string, '|', $pos + 1)) !== false) {
$positions[] = $pos;
}
I'm still not sure I understood why you can't just use explode() for this, though.
<?php
$string = 'I have | been very busy lately and need to go | to bed early';
$parts = explode('|', $string);
$words = array();
foreach ($parts as $s) {
$words[] = str_word_count($s);
}