I have a little issue I'm trying to find a solution for.
Basically, imagine you have the following string:
$string = 'Hello I am a string';
And you'd like it to end with something like the folowing:
$string = 'Hello I am a string';
Simply, replacing the last occurrence of a space, with a non-breaking space.
I'm doing this because I don't want the last word in a heading to be on its own. Simply because when it comes to headings:
Hello I am a
string
Doesn't look as good as
Hello I am
a string
How does one do such a thing?
Code from this example will do the trick:
// $subject is the original string
// $search is the thing you want to replace
// $replace is what you want to replace it with
substr_replace($subject, $replace, strrpos($subject, $search), strlen($search));
echo preg_replace('/\s(\S*)$/', ' $1', 'Hello I am a string');
Output
Hello I am a string
CodePad.
\s matches whitespace characters. To match a space explictly, put one in (and change \S to [^ ]).
This would do the trick:
$string = preg_replace('/([\s\S]+)\s(\w)$/','$1 $2',$string);
as per pounndifdef's answer, however i needed to decode the HTML entity like so:
substr_replace($subject, html_entity_decode($replace), strrpos($subject, $search), strlen($search));
also worked using alex's answer:
preg_replace('/\s(\S*)$/', html_entity_decode(' ').'$1', 'Hello I am a string');
Use str_replace() like normal, but reverse the string first. Then, reverse it back.
Related
I have a load of labels which are camel case. Some examples are
whatData
whoData
deliveryDate
importantQuestions
What I am trying to do is this. Any label which has the word Data needs to have this word removed. At the point of the capital letter, I need to provide a space. Finally, everything should be uppercase. I have done the removal of Data and the uppercase by doing this ($data->key is the label)
strtoupper(str_replace('Data', '', $data->key))
The part I am struggling with is adding the spaces between words. So basically the above words should end up like this
WHAT
WHO
DELIVERY DATE
IMPORTANT QUESTIONS
How can I factor in the last part of this?
Thanks
It will add spaces before every capital letters. Try this:
$String = 'whatData';
$Words = preg_replace('/(?<!\ )[A-Z]/', ' $0', $String);
Problem
Your regex '~^[A-Z]~' will match only the first capital letter. Check out Meta Characters in the Pattern Syntax for more information.
Your replacement is a newline character '\n' and not a space.
Solution
Use preg_replace(). Try below code.
$string = "whatData";
echo preg_replace('/(?<!\ )[A-Z]/', ' $0', $string);
Output
what Data
Try following:
$string = 'importantQuestions';
$string = strtoupper(ltrim(preg_replace('/[A-Z]/', ' $0', $string)));
echo $string;
This will give you output as:
IMPORTANT QUESTIONS
Try this:
preg_split: split on camel case
array_map: UPPER case all the element
implode: Implode the array
str_replace: Replace the `DATE` with empty
trim: trim the white spaces.
Do this simple things:
echo trim(str_replace("DATE", "", implode(" ", array_map("strtoupper", preg_split('/(?=[A-Z])/', 'deliveryDate', -1, PREG_SPLIT_NO_EMPTY))))); // DELIVERY
This is result exactly what you want.
I couldn't find the solution using search.
I am looking for a php solution to remove all character BEFORE the second occurance of and underscore (including the underscore)
For example:
this_is_a_test
Should output as:
a_test
I currently have this code but it will remove everything after the first occurance:
preg_replace('/^[^_]*.s*/', '$1', 'this_is_a_test');
Using a slightly different approach,
$s='this_is_a_test';
echo implode('_', array_slice( explode( '_', $s ),2 ) );
/* outputs */
a_test
preg_replace('/^.*_.*_(.*)$/U', '$1', 'this_is_a_test');
Note the U modifier which tells regex to take as less characters for .* as possible.
You can also use explode, implode along with array_splice like as
$str = "this_is_a_test";
echo implode('_',array_splice(explode('_',$str),2));//a_test
Demo
Why go the complicated way? This is a suggestion though using strrpos and substr:
<?php
$str = "this_is_a_test";
$str_pos = strrpos($str, "_");
echo substr($str, $str_pos-1);
?>
Try this one.
<?php
$string = 'this_is_a_test';
$explode = explode('_', $string, 3);
echo $explode[2];
?>
Demo
I'm still in favor of a regular expression in this case:
preg_replace('/^.*?_.*?_/', '', 'this_is_a_test');
Or (which looks more complex here but is easily adjustable to N..M underscores):
preg_replace('/^(?:.*?_){2}/', '', 'this_is_a_test');
The use of the question mark in .*? makes the match non-greedy; and the pattern has been expanded from the original post to "match up through" the second underscore.
Since the goal is to remove text the matched portion is simply replaced with an empty string - there is no need for a capture group or to use such as the replacement value.
If the input doesn't include two underscores then nothing is removed; such can be adjusted, very easily with the second regular expression, if the rules are further clarified.
$text = 'Hello #demo here!';
$pattern = '/#(.*?)[ ]/';
$replacement = '<strong>${1}</strong> ';
echo preg_replace($pattern, $replacement, $text);
This works, I get HTML like this: Hello <strong>demo</strong> here!. But this not works, when that #demo is at the end of string, example: $text = 'Hello #demo';. How can I change my pattern, so it will return same output whenever it is end of the string or not.
Question 2:
What if the string is like $text = 'Hello #demo!';, so it will not put ! as bolded text? Just catch space, end of string or not real-word.
Sorry for bad English, hope you know what I need.
In order to select a word beginning with the # symbol, this regex will work:
$pattern = "/#(\w+)\b/"
`\w` is a short hand character class for `[a-zA-Z0-9_]`. `\b` is an anchor for the beginning or end of a word, in this case the end. So the regex is saying: select something starting with an '#' followed by one or more word characters until the end of the word is reached.
Reference: http://www.regular-expressions.info/tutorial.
You could use a word boundary, that's what they're for:
$pattern = '/#(.+?)\b/';
This will work for question 2 also
You can add an option to match the end of the string:
#(.*?)(?= |\p{P}?$)
Replace with <strong>$1</strong>.
You can also use \p{P} (any Unicode punctuation symbol) to prevent punctuation from bold formatting.
Here is a demo.
I have a string that contains many underscores followed by words ex: "Field_4_txtbox" I need to find the last underscore in the string and remove everything following it(including the "_"), so it would return to me "Field_4" but I need this to work for different length ending strings. So I can't just trim a fixed length.
I know I can do an If statement that checks for certain endings like
if(strstr($key,'chkbox')) {
$string= rtrim($key, '_chkbox');
}
but I would like to do this in one go with a regex pattern, how can I accomplish this?
The matching regex would be:
/_[^_]*$/
Just replace that with '':
preg_replace( '/_[^_]*$/', '', your_string );
There is no need to use an extremly costly regex, a simple strrpos() would do the job:
$string=substr($key,0,strrpos($key,"_"));
strrpos — Find the position of the last occurrence of a substring in a string
You can also just use explode():
$string = 'Field_4_txtbox';
$temp = explode('_', strrev($string), 2);
$string = strrev($temp[1]);
echo $string;
As of PHP 5.4+
$string = 'Field_4_txtbox';
$string = strrev(explode('_', strrev($string), 2)[1]);
echo $string;
I'm detecting #replies in a Twitter stream with the following PHP code using regexes.
$text = preg_replace('!^#([A-Za-z0-9_]+)!', '#$1', $text);
$text = preg_replace('! #([A-Za-z0-9_]+)!', ' #$1', $text);
How can I best combine these two rules without false flagging email#domain.com as a reply?
OK, on a second thought, not flagging whatever#email means that the previous element has to be a "non-word" item, because any other element that could be contained in a word could be signaled as an email, so it would lead:
!(^|\W)#([A-Za-z0-9_]+)!
but then you have to use $2 instead of $1.
Since the ^ does not have to stand at the beginning of the RE, you can use grouping and | to combine those REs.
If you don't want re-insert the whitespace you captured, you have to use "positive lookbehind":
$text = preg_replace('/(?<=^|\s)#(\w+)/',
'#$1', $text);
or "negative lookbehind":
$text = preg_replace('/(?<!\S)#(\w+)/',
'#$1', $text);
...whichever you find easier to understand.
Here's how I'd do the combination
$text = preg_replace('!(^| )#([A-Za-z0-9_]+)!', '$1#$2', $text);
$text = preg_replace('/(^|\W)#(\w+)/', '#$2', $text);
preg_replace('%(?<!\S)#([A-Za-z0-9_]+)%', '#$1', $text);
(?<!\S) is loosely translated to "no preceding non-whitespace character". Sort of a double-negation, but also works at the start of the string/line.
This won't consume any preceding character, won't use any capturing group, and won't match strings such as "foo-#host.com", which is a valid e-mail address.
Tested:
Input = 'foo bar baz-#qux.com bee #def goo#doo #woo'
Output = 'foo bar baz-#qux.com bee #def goo#doo #woo'
Hu, guys, don't push too far... Here it is :
!^\s*#([A-Za-z0-9_]+)!
I think you can use alternation,: so look for the beginning of a string or a space
'!(?:^|\s)#([A-Za-z0-9_]+)!'