I have a field in my table that holds a string denoting some object levels, like so:
"<3<"
"<3<5<"
"<3<5<49<"
etc.
I have a function that is to remove a level from such a string, without knowing the position of the level in the string itself. Concretely, I would like to remove "3". The result should be:
"0"
"<5<"
"<5<49<"
If I would, however, want to remove 5, and not 3, the result should be this:
"<3<"
"<3<"
"<3<49<"
Lastly, if I chose to remove 49 instead of 3 or 5, I would like to get this:
"<3<"
"<3<5<"
"<3<5<"
As you can see, the position of the substring that is to be removed varies - sometimes it's the leftmost one, sometimes in the middle, sometimes the rightmost one. What is important after all this is:
If the number I am removing is the only value, enclosed in "less than" signs (as in "<3<" while removing 3), the new result must be 0.
If the number I am removing is not the only value, the only thing that matters is that the final notation stays the same - as in, the entire string must remain enclosed in "less than" symbols, and substrings of multiple "less than" symbols in a row must not happen (as in, "3<<5<" is not allowed).
Is there an easy regex way to handle this with php and mysql, or should I just make 3 manual checks?
P.S. While I may have posed it as such, this is not homework but an actual work issue.
for each line two replacements: (for example, you want to remove "3")
replace "^<3<$" -> "0";
replace "<3" -> "";
You can do it in 2 steps.
Suppose your input is this
"<3<"
"<3<5<"
"<3<5<49<"
and you want to remove number 3:
Step 1. Since the values always start with "<", you can try to replace "<3" with "". Then the input becomes
"<"
"<5<"
"<5<49<"
Step 2. Replace strings which EQUALS "<" with 0. Then you can get
"0"
"<5<"
"<5<49<"
It's the same if you want to remove 5 or 49.
I think you can easily use regex to do these steps.
In the first step:
replace "<3(?=<)"
I'ts important to use lookaheads, otherwise you could be replacing something like *<3*4 and that's not what you want.
Second step:
replace "^<$" with "0"
Related
How can I get, into an array, all occurrences of this pattern 4321[5-9][7-9]{6} but excluding, for example, the occurrences where there is a digit immediately before the value, or immediately after it?
For instance, 43217999999 should be valid but 143217999999 (note the number 1 at the beginning) should not be valid.
As the first example, 432179999991 shouldn't be valid because of the 1 that it has in the end.
The added difficulty, at least for me, is that I have to parse this in whatever position I can find it inside a string.
The string looks like this, literally:
43217999997 / 543217999999 // 43217999998 _ 43217999999a43216999999-43216999999 arandomword 432159999997
As you would be able to note, it has no standard way of separating the values (I marked in bold the values that would make it invalid, so I shouldn't match those)
My idea right now is something like this:
(\D+|^)(4321[5-9][7-9]{6})(\D+|$)
(\D+|^) meaning that I expect in that position the start of the string or at least one non-digit and (\D+|$) meaning that I expect there the end of the string or at least one non-digit.
That obviously doesn't do what I picture in my head.
I also tried do it in two steps, first:
preg_match_all("/\D+4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}\D+|4321[5-9][7-9]{6}$/", $input, $outputArray);
and then:
for($cont = 0; $cont < count($outputArray); $cont++) {
preg_match("/4321[5-9][7-9]{6}/", $outputArray[0][$cont], $outputArray2[]);
}
so I can print
echo "<pre>" . print_r($outputArray2, true) . "</pre>";
but that doesn't let me exclude the ones that have a number before the start of the value (5432157999999 for example), and then, I am not making any progress with my idea.
Thanks in advance for any help.
If you literally want to check if there is no digit before or after the match you can use negative look ahead and look behind.
(?![0-9]) at the end means: "is not followed by 0-9"
(?<![0-9]) at the start means: "is not preceded by 0-9"
See this example https://regex101.com/r/6xbmJk/1
I have a php pull down that I select an item and delete
all files associated with it.
It works well if there was only 5 or 6. After I put the
first 4 to test and get it working I realized it could
take a very long time to enter in a couple hundred and
would blot the script.
Not knowing enough about for and while loops is there
anyone that might have a way to help?
There will never be more than one set deleted at a time.
Thanks in advance.
<?php
$workitem = $_POST["workitem"];
$workdirPAth = "/var/work.files/";
if($workitem == 'item1.php')
{
unlink("$workdirPath/page1.php");
unlink("$workdirPath/temp1.php");
unlink("$workdirPath/all1.php");
}
if($workitem == 'item2.php')
{
unlink("$workdirPath/page2.php");
unlink("$workdirPath/temp2.php");
unlink("$workdirPath/all2.php");
}
if($workitem == 'item3.php')
{
unlink("$workdirPath/page3.php");
unlink("$workdirPath/temp3.php");
unlink("$workdirPath/all3.php");
}
if($workitem == 'item4.php')
{
unlink("$workdirPath/page4.php");
unlink("$workdirPath/temp4.php");
unlink("$workdirPath/all3.php");
?>
Some simple pattern matching and substitution is all you need here.
First, the code:
1. if (preg_match('/^item(\d+)\.php$/', $workitem, $matches)) {
2. $number = $matches[1];
3. foreach(array('page','temp','all') as $base) {
4. unlink("$workdirPath/$base$number.php");
5. }
6. } else {
7. # unrecognized work item value; complain to user or whatever
8. }
The preg_match function takes a pattern, a string, and an array. If the string matches the pattern, the parts that match are stored in the array. The particular type of pattern is a *p*erl5-compatible *reg*ular expression, which is where the preg_ part of the name comes from.
Regular expressions are scary-looking to the uninitiated, but they're a handy way to scan a string and get some values out of it. Most characters just represent themselves; the string "foo" matches the regular expression /foo/. But some characters have special meanings that let you make more general patterns to match a whole set of strings where you don't have to know ahead of time exactly what's in them.
The /s just mark the beginning and end of the actual regular expression; they're there because you can stick additional modifier flags inside the string along with the expression itself.
The ^and $ arepresent the beginning and end of the string. "/foo/" matches "foo", but also "foobar", "bunnyfoofoo", and so on - any string that contains "foo" will match. But /^foo$/ matches only "foo" exactly.
\d means "any digit". + means "one or more of that last thing". So \d+ means "one or more digits".
The period (.) is special; it matches any character at all. Since we want a literal period, we have to escape it with a backslash; \. just matches a period.
So our regular expression is '/^item\d+\.php$/', which will match any itemnumber.php filename. But that's not quite enough. The preg_match function is basically a binary test: does the string match the pattern or not, yes or no? In this case, it's not enough to just say "yup, the string is valid"; we need to know which items specifically the user specified. That's what capture groups are for. We use parentheses to say "remember what matched this part", and provide an array name that gets filled with those remembrances.
The part of the string that matches the whole regular expression (which may not be the whole string, if the regular expression isn't anchored with ^...$ like this one is) is always put in element 0 of the array. If you use parentheses in the regular expression, then the part of the string that matches the part of the regular expression inside the first pair of parentheses is stored in element 1 of the array; if there's a second set of parentheses, the matching part of the string goes in element 2 of the array, and so on.
So we put parentheses around our number ((\d+)) and then the actual number will be remembered in element 1 of our $matches array.
Great, we have a number. Now we just need to use it to build up the filenames we want to delete.
In each case, we want to delete three files: page$n.php, temp$n.php, and all$n.php, where $n is the number we extracted above. We could just put three unlink calls, but since they're all so similar, we can use a loop instead.
Take the different prefixes that are the same no matter the number, and make an array out of them. Then loop over that array. In the body of the loop, the variable $base will contain whichever element of the array it's currently on. Stick that between the $workdirPath prefix and the $number we got from the match, append .php, and that's your file. unlink it and go back to the top of the loop to grab the next one.
I am stuck with the issue as currently the result is quite unexpected. I am calculating a hashed keyword length and it is surely giving me an unexpected result.
echo strlen("$2a$08$MphfRBNtQMLuNro5HOtw3Ovu20cLgC0VKjt6w7zrKXfj1bv8tNnNa");
Output - 6
Let me know the reason for this and why it is outputting 6 as a result.
Codepad Link - http://codepad.org/pLARBx6F
You must use single quotes '. With the double quotes ("), due to the $ in your string, parts of it get interpreted as variables.
Generally, it's not a bad idea to get accustomed to using single quotes unless you specifically need doubles.
Look at the "variables" contained here. They would be $2a, $08, and $MphfRBNtQM......
The first two couldn't be variables as they start with a number, thus, the 6 characters. The third one indeed could be a proper variable, but since it isn't set, it's empty.
Use the below code to calculate the string length -
echo strlen('$2a$08$MphfRBNtQMLuNro5HOtw3Ovu20cLgC0VKjt6w7zrKXfj1bv8tNnNa');
You need to use single quotes, as at the third occurrence of the symbol $, a alphabet is starting after it and it get treated as a new variable. So before this third occurrence of $ only 6 character were there and you were getting string length as 6
Try following
<?php
echo strlen('$2a$08$MphfRBNtQMLuNro5HOtw3Ovu20cLgC0VKjt6w7zrKXfj1bv8tNnNa');
?>
If you change your string and remove rest of '$' signs except the first one, then this will work fine because by adding $ it gets a special meaning in PHP.
I am trying to learn regex in PHP and messing around with the preg_split function.
It doesn't appear to be correct though, or my understanding is completely wrong.
The test code i am using is:
$string = "test ing ";
var_dump(preg_split('/t/', $string));
I would expect to get an array like the following:
[0] => "es" [1] => " ing "
but the following is being returned:
[0] => "" [1] => "es" [2] => " ing "
Why is there an empty string at the start?
I understand that i can use the PREG_SPLIT_NO_EMPTY flag to filter this but it shouldnt be there to begin with. Should it?
Why shouldn't it? This is exactly how it works. The semantics of a split operation are that you have a string of this format:
value-delimiter-value-delimiter-value-...-delimiter-value
(Note that it is starting and ending with a value, not a delimiter.)
So if your string starts with a delimiter, it is absolutely valid to assume that there is an empty value before that delimiter (since the delimiter is supposed to split something into two). You wouldn't generally want to reject the empty string between two consecutive ts either, would you?
And this is exactly what PREG_SPLIT_NO_EMPTY is for. You use it whenever you do want to get rid of those empty strings.
As a simple example why you would want the default behavior, just think of CSV files. You want to split a line at (for example) ;. You usually also want to allow for empty values. Now if the value in your first column was empty (meaning the line will start with ;, and you chopped that first empty string away completely, then suddenly all indices in the resulting array would correspond to different columns. This is why you want to keep those empty strings as well. In many cases you know how many delimiters there are, and hence how many values - and you want to be able to identify which value belongs at which position. Even if some of them are empty.
It's working 100% correct. The first character is a 't', so it's splitting on that 't' first. Before the first 't' there is nothing, so the array result start with an entry of empty string.
It's happening because of the t at the beginning of your string. If you don't use the PREG_SPLIT_NO_EMPTY option, preg_split will treat an empty string as a valid split.
Think of it this way: Everywhere preg_split sees a t, it chops the string into two chunks: the chunk before the t, and the chunk after it. Even if one of the chunks doesn't have anything in it, it still counts. That piece is just an empty string.
For some applications, this would be perfectly useful -- for example, say you wanted to replace each t with something, but the replacement was too complicated to just use preg_replace. The language wants you to be able to choose, so it keeps the empty split unless you explicitly tell it not to with PREG_SPLIT_NO_EMPTY.
I "inherited" a buggy PHP page. I'm not an expert of this language but I think I found the origin of the bug. Inside a loop, the page sends a formatted string to the server: the string I found in the HTML page is like this one:
2011-09-19__full_1
so, it seems we have three parts:
a date (0,10);
a string (10,6);
a final number (17,1);
The code the handles this situation is the following:
$datagrid[] = array("date"=>substr($post_array_keys[$i], 0, 10),"post_mode"=>substr($post_array_keys[$i], 10, 6),"class_id"=>substr($post_array_keys[$i], 17, 1),"value"=>$_POST[$post_array_keys[$i]]);
What happens: the final number can contain more than one character, so this piece:
"class_id"=>substr($post_array_keys[$i], 17, 1)
is not correct because it seems to retrieve only one character starting from the 17th (and this seems to cause strange behaviors to the website).
Being the whole number the last part of the string, to get the entire number could I safely change this line this way?
"class_id"=>substr($post_array_keys[$i], 17, strlen($post_array_keys[$i])-17);
If you change the code the way you suggest you would get the numbers at the end starting in position 17. The original code gets only the first digit. Your code would get all the digits.
And it seems you did your homework the line
$datagrid[] = array("date"=>substr($post_array_keys[$i], 0, 10),"post_mode"=>substr($post_array_keys[$i], 10, 6),"class_id"=>substr($post_array_keys[$i], 17, 1),"value"=>$_POST[$post_array_keys[$i]]);
does give you a very good clue of what you should expect in the variable:
first 10 is the date
then you have 6 chars for post_mode
then you have 1 char for class_id
If you also confirmed that sometimes the class_id can be more than 1 char, your suggested change would give you the complete class_id at the end.
Good luck.
you could use
$array = explode("_", $string);
this functions returns an array with the elements in the string delimited by "_".
I suggest this because the double underscore may hide another value that is empty in that particular case.
If it's only the last integer causing trouble, you can use strrchr to get the "tail" of the string, starting with the last '_'.