I'm trying to check for
'#username'
'#username,'
'#username '
'#username.'
'#username. '
'#username:'
'#username: '
I currently have this:
$post->message = preg_replace(
'/# *('.preg_quote($speak['username'], '/').') *:/i',
'[url=\''.PAGE_URL.RELATIVE_WBB_DIR.'/index.php?page=User&userID='.$speak['toID'].'\']#'.$speak['username'].':[/url]',
$post->message);
Does anyone have any ideas how I can modify this to accept those inputs?
Modify your regex to add in the punctuation:
$post->message = preg_replace(
'/# *('.preg_quote($speak['username'], '/').')[:,.]? */i',
'[url=\''.PAGE_URL.RELATIVE_WBB_DIR.'/index.php?page=User&userID='.$speak['toID'].'\']#'.$speak['username'].':[/url]',
$post->message);
Note the added part:
/# *('.preg_quote($speak['username'], '/').')[:,.]? */i
^^^^^^
Which optionally matches one of those characters (colon, comma, period).
Here is a regular expression that should achieve what you are looking for:
/^#[a-zA-Z]+[:\.\,]?[ ]?$/
/^# // string starts with '#'
[a-zA-Z]+ // contains any letter at least once
[:\.\,]? // may contain any : , . zero or one time
[ ]?$ // may contain a whitespace zero or one time at end of string
Related
Given an address stored as a single string with newlines delimiting its components like:
1 Street\nCity\nST\n12345
The goal would be to replace all newline characters except the first one with spaces in order to present it like:
1 Street
City ST 12345
I have tried methods like:
[$street, $rest] = explode("\n", $input, 2);
$output = "$street\n" . preg_replace('/\n+/', ' ', $rest);
I have been trying to achieve the same result using a one liner with a regular expression, but could not figure out how.
I would suggest not solving this with complicated regex but keeping it simple like below. You can split the string with a \n, pop out the first split and implode the rest with a space.
<?php
$input = explode("\n","1 Street\nCity\nST\n12345");
$input = array_shift($input) . PHP_EOL . implode(" ", $input);
echo $input;
Online Demo
You could use a regex trick here by reversing the string, and then replacing every occurrence of \n provided that we can lookahead and find at least one other \n:
$input = "1 Street\nCity\nST\n12345";
$output = strrev(preg_replace("/\n(?=.*\n)/", " ", strrev($input)));
echo $output;
This prints:
1 Street
City ST 12345
You can use a lookbehind pattern to ensure that the matching line is preceded with a newline character. Capture the line but not the trailing newline character and replace it with the same line but with a trailing space:
preg_replace('/(?<=\n)(.*)\n/', '$1 ', $input)
Demo: https://onlinephp.io/c/5bd6d
You can use an alternation pattern that matches either the first two lines or a newline character, capture the first two lines without the trailing newline character, and replace the match with what's captured and a space:
preg_replace('/(^.*\n.*)\n|\n/', '$1 ', $input)
Demo: https://onlinephp.io/c/2fb2f
I leave you another method, the regex is correct as long as the conditions are met, in this way it always works
$string=explode("/","1 Street\nCity\nST\n12345");
$string[0]."<br>";
$string[1]." ".$string[2]." ".$string[3]
I'm working with text content in UTF8 encoding stored in variable $title.
Using preg_replace, how do I append an extra space if the $title string is ending with:
upper/lower case character
digit
symbol, eg. ? or !
This should do the trick:
preg_replace('/^(.*[\w?!])$/', "$1 ", $string);
In essence what it does is if the string ends in one of your unwanted characters it appends a single space.
If the string doesn't match the pattern, then preg_replace() returns the original string - so you're still good.
If you need to expand your list of unwanted endings you can just add them into the character block [\w?!]
Using a positive lookbehind before the end of the line.
And replace with a space.
$title = preg_replace('/(?<=[A-Za-z0-9?!])$/',' ', $title);
Try it here
You may want to try this Pattern Matching below to see if that does it for you.
<?php
// THE REGEX BELOW MATCHES THE ENDING LOWER & UPPER-CASED CHARACTERS, DIGITS
// AND SYMBOLS LIKE "?" AND "!" AND EVEN A DOT "."
// HOWEVER YOU CAN IMPROVISE ON YOUR OWN
$rxPattern = "#([\!\?a-zA-Z0-9\.])$#";
$title = "What is your name?";
var_dump($title);
// AND HERE, YOU APPEND A SINGLE SPACE AFTER THE MATCHED STRING
$title = preg_replace($rxPattern, "$1 ", $title);
var_dump($title);
// THE FIRST var_dump($title) PRODUCES:
// 'What is your name?' (length=18)
// AND THE SECOND var_dump($title) PRODUCES
// 'What is your name? ' (length=19) <== NOTICE THE LENGTH FROM ADDED SPACE.
You may test it out HERE.
Cheers...
You need
$title=preg_replace("/.*[\w?!]$/", "\\0 ", $title);
I'm doing str_replace on a very long string and my $search is an array.
$search = array(
" tag_name_item ",
" tag_name_item_category "
);
$replace = array(
" tag_name_item{$suffix} ",
" tag_name_item_category{$suffix} "
);
echo str_replace($search, $replace, $my_really_long_string);
The reason why I added spaces on both $search and $replace is because I want to only match whole words. As you would have guessed from my code above, if I removed the spaces and my really long string is:
...
tag_name_item ...
tag_name_item_category ...
...
Then I would get something like
...
tag_name_item_sfx ...
tag_name_item_sfx_category ...
...
This is wrong because I want the following result:
...
tag_name_item_sfx ...
tag_name_item_category_sfx ...
...
So what's wrong?
Nothing really, it works. But I don't like it. Looks dirty, not well coded, inefficient.
I realized I can do something like this using regular expressions using the \b modifier but I'm not good with regex and so I don't know how to preg_replace.
A possible approach using regular expressions would/could look like this:
$result = preg_replace(
'/\b(tag_name_item(_category)?)\b/',
'$1' . $suffix,
$string
);
How it works:
\b: As you say are word boundaries, this is to ensure we're only matching words, not word parts
(: We want to use part of our match in the replacement string (tag_name_index has to be replaced with itself + a suffix). That's why we use a match group, so we can refer back to the match in the replacement string
tag_name_index is a literal match for that string.
(_category)?: Another literal match, grouped and made optional through use of the ? operator. This ensures that we're matching both tag_name_item and tag_name_item_category
): end of the first group (the optional _category match is the second group). This group, essentially, holds the entire match we're going to replace
\b: word boundary again
These matches are replaced with '$1' . $suffix. The $1 is a reference to the first match group (everything inside the outer brackets in the expression). You could refer to the second group using $2, but we're not interested in that group right now.
That's all there is to it really
More generic:
So, you're trying to suffix all strings starting with tag_name, which judging by your example, can be followed by any number of snake_cased words. A more generic regex for that would look something like this:
$result = preg_replace(
'/\b(tag_name[a-z_]*)\b/',
'$1' . $suffix,
$string
);
Like before, the use of \b, () and the tag_name literal remains the same. what changed is this:
[a-z_]*: This is a character class. It matches characters a-z (a to z), and underscores zero or more times (*). It matches _item and _item_category, just as it would match _foo_bar_zar_fefe.
These regex's are case-sensitive, if you want to match things like tag_name_XYZ, you'll probably want to use the i flag (case-insensitive): /\b(tag_name[a-z_]*)\b/i
Like before, the entire match is grouped, and used in the replacement string, to which we add $suffix, whatever that might be
To avoid the problem, you can use strtr that parses the string only once and chooses the longest match:
$pairs = [ " tag_name_item " => " tag_name_item{$suffix} ",
" tag_name_item_category " => " tag_name_item_category{$suffix} " ];
$result = strtr($str, $pairs);
This function replaces the entire whole word but not the substring with an array element which matches the word
<?PHP
function removePrepositions($text){
$propositions=array('/\b,\b/i','/\bthe\b/i','/\bor\b/i');
if( count($propositions) > 0 ) {
foreach($propositions as $exceptionPhrase) {
$text = preg_replace($exceptionPhrase, '', trim($text));
}
$retval = trim($text);
}
return $retval;
}
?>
See the entire example
I'm having troubles finding a regex that can retrieve the numbers 989552 in
/boards/989552-lettersandnumbers-morelettersandnumbers
What I'm searching in particular is can I retrieve what stands between /boards/ and the first -?
/boards/(\d+)-
Should store the numbers in the first match group.
Use .*/(\d+)- as .* is greedy it will match upto the last /:
$string = "/boards/989552-dgw25235-42352gdsgw";
echo preg_match('#.*/(\d+)-#',$string,$match);
echo $match[1];
>>> 989552
Here is an annotated solution.
<?php // RAY_temp_user1722791.php
error_reporting(E_ALL);
/*
I'm having troubles finding a regex that can retrieve the numbers 989552 in /boards/989552-lettersandnumbers-morelettersandnumbers
What I'm searching in particular is can I retrieve what stands between /boards/ and the first -?
*/
// A REGULAR EXPRESSION
$rgx
= '#' // REGEX DELIMITER
. '/boards/' // THE SEARCH STRING
. '(' // START A GROUP
. '\d+' // SOME DIGITS
. ')' // END OF THE GROUP
. '-' // THE DASH
. '#' // REGEX DELIMITER
;
// A TEST STRING
$str = 'in /boards/989552-lettersandnumbers';
// PEFORM THE MATCH
preg_match($rgx, $str, $mat);
// FIND THE NUMBERS IN THE FIRST MATCHED GROUP
var_dump($mat[1]);
I find it much easier to understand regular expressions when I write them out in vertical notation like this.
I want to replace leading space with with the same number of occurrences.
Explanation:
If one leading space exist in the input then it should replace it with one .
If two leading spaces exist in input then it should replace with two s.
If n leading spaces are exist in the input then it should replace it with exactly n number of times with .
Example 1:
My name is XYZ
Output:
My name is XYZ
Example 2:
My name is XYZ
Output:
My name is XYZ
How can I replace only leading spaces, using a PHP regular expression?
preg_replace('/\G /', ' ', $str);
\G matches the position where the last match ended, or the beginning of the string if there isn't any previous match.
Actually, in PHP it matches where the next match is supposed to begin. That isn't necessarily the same as where the previous match ended.
$len_before = strlen($str);
$str = ltrim($str, ' ');
$len_after = strlen($str);
$str = str_repeat(' ', $len_before - $len_after) . $str;
Using preg_replace there is also
$str = preg_replace('/^( +)/e', 'str_repeat(" ", strlen("$1"))', $str);
but note that it uses the /e flag.
See http://www.ideone.com/VWNKZ for the result.
Use:
preg_replace('/^ +/m', ' ', $str);
You can test it here.
Use preg_match with PREG_OFFSET_CAPTURE flag set. The offset is the length of the "spaces". Then use str_repeat with the offset.