How to replace text over multiple lines using preg_replace
If this weren't HTML, I'd tell you to use the DOTALL modifier to change the meaning of .
from 'match everything except new line' to 'match everything':
preg_replace('/(.*)<\/div>/s','abc',$body);
But this is HTML, so use an HTML parser instead.
PHP preg_replace guids over multiple lines
You can use
preg_replace_callback(
'/^(?:\s?[a-f\d]){8}\s?(?:-(?:\s?[a-f\d]){4}){4}(?:\s?[a-f\d]){8}$/mi',
function($m) {
return file_get_contents(preg_replace("~\s+~", "", $m[0]) . ".php");
},
$lines
);
See the regex demo.
The \s?
inside the pattern allows matching an optional whitespace anywhere in between each char of a match. Also, with regard to the regex pattern, you need to use m
flag to make ^
and $
match line boundaries (start/end of the line, not just start/end of the whole string).
You can't pass ${1}
into a function within preg_replace
replacement argument, you need a preg_replace_callback
so that the match could be evaluated before passing it to a function.
PHP preg_replace not matching multiple lines
Use the s
modifier instead of the m
modifier.
The s
modifier allows .
to match newlines.
The m
modifier makes ^
and $
match the start and end of individual lines, as opposed to the start and end of the entire string.
Side-note: The preferred syntax for the replacement is <div>$1</div>
preg_replace multiline match but preserve new lines
Ok one line using the tokenizer (Ugly thing inside):
php -r 'echo array_reduce(token_get_all(file_get_contents($argv[1])),function($c,$i){return $i[0]==321?$c.$i[1]:$c.str_repeat("\n",@count_chars($i.$i[1])[10]);});'
demo
Advantage of the tokenizer: even a string like "abc <?php echo '?>'; ?> def"
is correctly parsed.
321 is the value of the constant T_INLINE_HTML
(all that isn't between php tags).
10 is ASCII code for the newline character (LF). (by default, count_chars
returns an associative array with the ASCII codes as keys and the number of occurrences as values).
The ugly thing is $i.$i[1]
that concatenates an array with a string or a string with something not defined. @
avoids the warnings and notices. Whatever, this trick avoids a test and the number of newline characters is preserved. (see what returns token_get_all
to understand the problem).
Or with DOMDocument
:
php -r '$d=DOMDocument::loadHTMLFile($argv[1],8196);foreach((new DOMXPath($d))->query("//processing-instruction()")as$p)$p->parentNode->replaceChild($d->createTextNode(preg_replace("~\S+~","",$p->nodeValue)),$p);echo$d->saveHTML();'
Preg_replace with multiple lines(php)
The modifier you want is m
. You can find all modifiers here
That said, the easiest and better regex solution would be
"/\$this->session->set_flashdata\((.*?),\s*(.*?)\);/"
Notice how there's a ? after the .* in each. This is to stop greedy matching as with yours. Also notice that the modifier isn't required either with the removal of the ^
and $
preg_replace replace line breaks across multiple lines between two symbols
You can use
preg_replace('~(?:\G(?!\A)|^[@.])[^{]*?\K\s+~m', ' ', $text)
See the regex demo. Details:
(?:\G(?!\A)|^[@.])
- end of the previous successful match (\G(?!\A)
) or (|
) start of string (^
) and then@
or.
[^{]*?
- any zero or more (but as few as possible) chars other than{
\K
- match reset operator that discards all text matched so far in the overall match memory buffer\s+
- any one or more whitespace chars.
Note the m
flag that is necessary to make ^
match start of a line, not just start of a whole string.
See the PHP demo:
$text = ".a {\r\n // rules\r\n}\r\n\r\n.a-b,\r\n.a-b .b, .a-b.s\r\n.x .y, .x {\r\n // rules\r\n}\r\n\r\n@a {\r\n // rules\r\n}\r\n\r\n@k {\r\n // rules\r\n}";
echo preg_replace('~(?:\G(?!\A)|^[@.])[^{]*?\K\s+~m', ' ', $text);
PHP Regex preg_replace multiple values between parentheses
You're going to need to go two layers, first pull everything between the []
then replace the values as needed. You can use preg_replace_callback
to accomplish this.
$string= '[mycode="gallery" type="single" id="1" data="only"]';
echo preg_replace_callback('/\[([^\]]+)\]/', function($match) {
$string = preg_replace('/\h*mycode="([^"]+)"\h*/', '$1/mycode', $match[1]);
$string = preg_replace('/\h*type="([^"]+)"\h*/', 'mycode_$1.php', $string);
$string = preg_replace('/\h*id="([^"]+)"\h*/', '?id=$1', $string);
$string = preg_replace('/\h*data="([^"]+)"\h*/', '&data=$1', $string);
return $string;
}, $string);
Your regex didn't work for a few reasons:
- Your strings don't end with
]
- Backslashes in regex escape or create meta characters,
\d
is a number\t
is a tab. - If building a URL you don't want a double quote in the returned value
- You also need to trim the leading and trailing whitespaces
Demo: https://3v4l.org/KDD0B
Related Topics
Multiple Http Get Parameters with the Same Identifier
How to Convert PHP Regex to JavaScript Regex
How to Download a File on Clicking the Name of File Using PHP
Pdo: Call to a Member Function Fetch() on a Non-Object
Convert All Node's Attributes into Child Nodes
Laravel Validation Attributes "Nice Names"
Setting Up Domainkeys/Dkim in a PHP-Based Smtp Client
What Does Bind_Param Accomplish
PHP Dynamic Name for Object Property
What Does $K => $V in Foreach($Ex as $K=>$V) Mean
How to Sum All Values of a Specific Array Key Recursively
Simple Xml Add Namespaced Child
Add a Line Break in Woocommerce Product Titles