I am trying to run following regular expression based function in php where in the end am returning the output.
function vg_excerpt_more( $output ) {
$string = $output;
$pattern_auto_excerpt = '#([...]</p>)$#';
$pattern_manual_excerpt = '#(</p>)$#';
$replacement = ' [Continue...]</p>';
if ( preg_match( $pattern_auto_excerpt, $string ) ) {
$pattern = $pattern_auto_excerpt;
} else if ( preg_match( $pattern_manual_excerpt, $string ) ) {
$pattern = $pattern_manual_excerpt;
}
$output = preg_replace( $pattern, $replacement, $string );
return $output;
}
add_filter( 'the_excerpt', 'vg_excerpt_more' );
add_filter( 'excerpt_more', 'vg_excerpt_more' );
Well, the string could either end in [...]</p> OR </p> so I have to check the two cases.
The problem is, it is throwing warnings as -
WARNING: PREG_MATCH(): COMPILATION FAILED: POSIX COLLATING ELEMENTS
ARE NOT SUPPORTED AT OFFSET 1 in - 'preg_match( $pattern_auto_excerpt,
$string )'
and
WARNING: PREG_REPLACE(): EMPTY REGULAR EXPRESSION in - '$output =
preg_replace( $pattern, $replacement, $string );'
EDIT:
After useful replies by #user1852180 I moved ahead and did this -
function vg_excerpt_more( $output ) {
$string = $output;
$pattern = '';
// $pattern_auto_excerpt = '#(\[...\]</p>)$#';
$pattern_auto_excerpt = '#(\[(?:\.|…)+\])#';
$pattern_manual_excerpt = '#(</p>)$#';
$replacement = ' [Continue...]</p>';
if ( preg_match( $pattern_auto_excerpt, $string ) ) {
$pattern = '#(\[(?:\.|…)+\]</p>)$#';
if ( preg_match( $pattern, $string ) ) {
return preg_replace( $pattern, $replacement, $string ) . "Dummy2";
}
} else if ( preg_match( $pattern_manual_excerpt, $string ) ) {
$pattern = $pattern_manual_excerpt;
return preg_replace( $pattern, $replacement, $string ) . "Dummy";
}
return $output;
}
add_filter( 'the_excerpt', 'vg_excerpt_more' );
add_filter( 'excerpt_more', 'vg_excerpt_more' );
But am still seeing [...] in the frontend along with the replacement.
PS. It also never prints 'Dummy2', always 'Dummy'.
You need to escape the brackets in the first pattern, and the dot:
$pattern_auto_excerpt = '#(\[(?:\.|…)+\]</p>)$#';
You don't need to use the if/else to check if it has [...], let regex check that with the question mark:
function vg_excerpt_more( $output ) {
$pattern = '#(?:\[(?:\.|…)+\])?</p>$#';
$replacement = ' [Continue...]</p>';
return preg_replace( $pattern, $replacement, $output );
}
Related
I have 'create_function() in my PHP code:
function encode_code_in_comment( $source ) { $encoded = preg_replace_callback( '/\[(php|html|javascript|css|nginx|apache|terminal)\](.*?)\[\/\1\]/ims',
create_function(
'$matches',
'$matches[2] = preg_replace(
array("/^[\r|\n]+/i", "/[\r|\n]+$/i"), "",
$matches[2]);
return "<pre class=\"language-" . $matches[1] . "\"><code>" . esc_html( $matches[2] ) . "</code></pre>";'
),
$source );
if ( $encoded ) {
return $encoded;
} else {
return $source;
}}
I know that there are duplicates threads about the subject, but nevertheless, i'm really struggling to covert this to an anonymous function. How do i rewrite it?
Your main problem is that your code is badly formatted, making it hard to see where the create_function call begins and ends; here it is with some more logical linebreaks and indents:
function encode_code_in_comment( $source ) {
$encoded = preg_replace_callback(
'/\[(php|html|javascript|css|nginx|apache|terminal)\](.*?)\[\/\1\]/ims',
create_function(
'$matches',
'
$matches[2] = preg_replace(
array("/^[\r|\n]+/i", "/[\r|\n]+$/i"),
"",
$matches[2]
);
return "<pre class=\"language-" . $matches[1] . "\"><code>" . esc_html( $matches[2] ) . "</code></pre>";
'
),
$source
);
if ( $encoded ) {
return $encoded;
} else {
return $source;
}
}
From this and the documentation of create_function, we can see that the created function needs one argument, $matches, and to have a body starting $matches[2] = and ending </pre>";
Looking at the manual for anonymous functions we see that the new syntax is function(arguments) { body }, so instead of:
create_function('$matches', ... )
you want:
function($matches) { ... }
and in between, instead of:
'
$matches[2] = ...
...
... </pre>";
'
you want to just remove the quotes and leave the code:
$matches[2] = ...
...
... </pre>";
The body is in single quotes, and there are no escaped single quotes in there, so the code doesn't need any other changes.
I've a text file that I extracted all the domain addresses strting with http://
now I want to replace all the http://. in my matches array with "" but nothing is happening im not even getting an an error
$list = file_get_contents( 'file.txt' );
preg_match_all( "/http:\/\/.([a-z]{1,24}).([a-z^0-9-]{1,23}).([a-z]{1,3})/", $list, $matches );
for ($i=0; $i>=50; $i++) {
$pattern = array();
$replacement = array();
$pattern[0][$i] = "/http:\/\/.[w-w]{1,3}/";
$replacement[0][$i] = '';
preg_replace( $pattern[0][$i], $replacement[0][$i], $matches[0][$i] );
}
print_r($matches);
Your loop never runs because 0 >= 50 yields false. That said, what you're looking for is a map operation:
$matches = array_map(function($match) {
return preg_replace('~^http://w{1,3}~', '', $match);
}, $matches[0]);
print_r($matches);
preg_match_all has also problem. The period in regular expression matches any character.
$list = file_get_contents( 'file.txt' );
preg_match_all( "/http:\/\/([a-z]{1,24})\.([a-z^0-9-]{1,23})\.([a-z]{1,3})/", $list, $matches );
$pattern = "/http:\/\/(.[w-w]{1,3})/";
$replacement = '$1';
$matches[0] = preg_replace( $pattern, $replacement, $matches[0] );
print_r($matches);
I've got a string in PHP, MY_NEW_CLASS and I want to convert it to My_New_Class.
Is this possible using preg_replace or should I explode the string on the underscore, strtolower it, ucfirst it, then implode it back together?
I appreciate any help you can offer.
preg_replace by itself can't really do it I'd think, but it's not hard with a callback:
$str = preg_replace_callback('/(?<=\b|_)./',
function ($m) { return strtoupper($m[0]); },
strtolower($str));
Why use regex?
function camelize( $string ){
return strtoupper( $string{0} ) . strtolower( substr( $string, 1 ) );
}
function camelizeClass( $class ){
$parts = explode( '_', $class );
array_walk( $parts, function( &$value, $key ){
$value = camelize( $value );
});
return implode( '_', $parts );
}
echo camelizeClass( 'MY_NEW_CLASS' ); // My_New_Class
I need to search a string of words against a dictionary of words(txt file) and capitalize any word that is not found.
I'm trying to split the string into an array of words and check them against the unix /usr/dict/words dictionary. If a match is found for the word it gets lcfirst($word) if no match then ucfirst( $word )
The dictionary is opened and put into an array using fgetcsv (I also tried using fgets and exploding on end of line).
function wnd_title_case( $string ) {
$file = fopen( "/users/chris/sites/wp-dev/trunk/core/words.txt", "rb" );
while ( !feof( $file ) ) {
$line_of_text = fgetcsv( $file );
$exceptions = array( $line_of_text );
}
fclose( $file );
$delimiters = array(" ", "-", "O'");
foreach ( $delimiters as $delimiter ) {
$words = explode( $delimiter, $string );
$newwords = array();
foreach ($words as $word) {
if ( in_array( strtoupper( $word ), $exceptions ) ) {
// check exceptions list for any words that should be lower case
$word = lcfirst( $word );
} elseif ( !in_array( $word, $exceptions ) ) {
// everything else capitalized
$word = ucfirst( $word );
}
array_push( $newwords, $word );
}
$string = join( $delimiter, $newwords );
}
$string = ucfirst( $string );
return $string;
}
I have verified that the file gets opened.
The desired output: Sentence case title string with proper nouns capitalized.
The current output: Title string with every word capitalized
Edit:
Using Jay's answer below I came up with a workable solution. My first problem was that my words dictionary contained both capitalized and non capitalized words so I found a proper names dictionary to to check against using a regex callback. It's not perfect but gets it right most of the time.
function title_case( $string ) {
$fp = #fopen( THEME_DIR. "/_/inc/propernames", "r" );
$exceptions = array();
if ( $fp ) {
while( !feof($fp) ) {
$buffer = fgets( $fp );
array_push( $exceptions, trim($buffer) );
}
}
fclose( $fp );
$content = strtolower( $string );
$pattern = '~\b' . implode ( '|', $exceptions ) . '\b~i';
$content = preg_replace_callback ( $pattern, 'regex_callback', $content );
$new_content = $content;
return ucfirst( $new_content );
}
function regex_callback ( $data ) {
if ( strlen( $data[0] ) > 3 )
return ucfirst( strtolower( $data[0] ));
else return ( $data[0] );
}
The simplest way to do this with regex is to do the following
convert your text to all uppercase first letters $content = ucwords($original_content);
Using your array of words in the dictionary, create a regex by imploding all your words with a pipe character |, and surrounding it with boundary markers and delimiters followed by the case insensitive flag, so you would end up with ~\bword1|word2|word3\b~i (obviously with your large list)
create a function to lower the matched value using strtolower to be used with preg_replace_callback
An example of a working demo is this
function regex_callback($data) {
return strtolower($data[0]);
}
$original_content = 'hello my name is jay gilford';
$words = array('hello', 'my', 'name', 'is');
$content = ucwords($original_content);
$pattern = '~\b' . implode('|', $words) . '\b~i';
$content = preg_replace_callback($pattern, 'regex_callback', $content);
echo $content;
You could also optionally use strtolower to begin with on the content for consistency. The above code outputs hello my name is Jay Gilford
I have a list of words in an array. I need to look for matches on a string for any of those words.
Example word list
company
executive
files
resource
Example string
Executives are running the company
Here's the function I've written but it's not working
$matches = array();
$pattern = "/^(";
foreach( $word_list as $word )
{
$pattern .= preg_quote( $word ) . '|';
}
$pattern = substr( $pattern, 0, -1 ); // removes last |
$pattern .= ")/";
$num_found = preg_match_all( $pattern, $string, $matches );
echo $num_found;
Output
0
$regex = '(' . implode('|', $words) . ')';
<?php
$words_list = array('company', 'executive', 'files', 'resource');
$string = 'Executives are running the company';
foreach ($words_list as &$word) $word = preg_quote($word, '/');
$num_found = preg_match_all('/('.join('|', $words_list).')/i', $string, $matches);
echo $num_found; // 2
Make sure you add the 'm' flag to make the ^ match the beginning of a line:
$expression = '/foo/m';
Or remove the ^ if you don't mean to match the beginning of a line...