在PHP中编写一个简单的preg_replace

时间:2008-10-10 16:49:14

标签: php regex

我不是一个程序员,但是我需要在PHP中编写一个简单的 preg_replace 语句来帮助我使用WordPress插件。基本上,我需要一些代码来搜索字符串,拉出视频ID,并返回插入视频ID的嵌入代码。

换句话说,我正在寻找这个:

[youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1]

并希望用此替换它(保持视频ID相同):

param name="movie" value="http://www.youtube.com/v/VIDEO_ID_HERE&hl=en&fs=1&rel=0

如果可能的话,如果你能解释一下你如何在搜索模式中使用各种斜线,插入符号和Kleene星,即将它从grep翻译成英语,我将永远感激,这样我就可以学习。 : - )

谢谢!
麦克

5 个答案:

答案 0 :(得分:6)

小心!如果这是一个具有用户输入的BBCode风格的系统,那么这两个其他解决方案将使您容易受到XSS攻击。

你有几种方法可以保护自己免受这种伤害。让正则表达式明确禁止可能让你遇到麻烦的字符(或者只允许那些对youtube视频id有效的字符),或者实际上清理输入并使用preg_match,我将在下面说明RoBorg的正则表达式。

<?php

$input = "[youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1]";

if ( preg_match('/\[youtube=.*?v=(.*?)&.*?\]/i', $input, $matches ) )
{
    $sanitizedVideoId = urlencode( strip_tags( $matches[1] ) );
    echo 'param name="movie" value="http://www.youtube.com/v/' . $sanitizedVideoId . '&hl=en&fs=1&rel=0';
} else {
    //  Not valid input
}

以下是此类攻击行动的一个示例

<?php

$input = "[youtube=http://www.youtube.com/watch?v=\"><script src=\"http://example.com/xss.js\"></script>&hl=en&fs=1]";

//  Is vulnerable to XSS
echo preg_replace('/\[youtube=.*?v=(.*?)&.*?\]/i', 'param name="movie" value="http://www.youtube.com/v/$1&hl=en&fs=1&rel=0', $input );
echo "\n";

//  Prevents XSS
if ( preg_match('/\[youtube=.*?v=(.*?)&.*?\]/i', $input, $matches ) )
{
    $sanitizedVideoId = urlencode( strip_tags( $matches[1] ) );
    echo 'param name="movie" value="http://www.youtube.com/v/' . $sanitizedVideoId . '&hl=en&fs=1&rel=0';
} else {
    //  Not valid input
}

答案 1 :(得分:2)

$str = preg_replace('/\[youtube=.*?v=([a-z0-9_-]+?)&.*?\]/i', 'param name="movie" value="http://www.youtube.com/v/$1&hl=en&fs=1&rel=0', $str);

         /     - Start of RE
         \[    - A literal [  ([ is a special character so it needs escaping)
         youtube= - Make sure we've got the right tag
         .*?   - Any old rubbish, but don't be greedy; stop when we reach...
         v=    - ...this text
         ([a-z0-9_-]+?) - Take some more text (just z-a 0-9 _ and -), and don't be greedy.  Capture it using ().  This will get put in $1
         &.*?\] - the junk up to the ending ]
         /i - end the RE and make it case-insensitive for the hell of it

答案 2 :(得分:1)

如果可能的话,我会在这种情况下避免正则表达式,因为:谁保证第一个url中的查询字符串将始终采用该格式?

我使用parse_url($originalURL, PHP-URL-QUERY);然后遍历返回的数组,为查询字符串的v部分找到正确的'name = value'对: 类似的东西:

$originalURL = 'http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1';

foreach( parse_url( $originalURL, PHP_URL_QUERY) as $keyvalue )
{
    if ( strlen( $keyvalue ) > 2 && substr( $keyvalue, 0, 2 ) == 'v=' )
    {
        $videoId = substr( $keyvalue, 2 );
        break;
    }
}

$newURL = sprintf( 'http://www.youtube.com/v/%s/whatever/else', url_encode( $videoId ) );

P.S。写在SO文本框中,未经测试。

答案 3 :(得分:0)

$embedString = 'youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1';
preg_match('/v=([^&]*)/',$embedstring,$matches);
echo 'param name="movie" value="http://www.youtube.com/v/'.$matches[1].'&hl=en&fs=1&rel=0';

试试。

正则表达式/v=([^&]*)/以这种方式工作:

  • 搜索v=
  • 然后将匹配保存到括号内的模式$matches
  • [^&]告诉它匹配任何字符除了&符号('&amp;')
  • *告诉我们我们希望匹配中从0到任意数量的任何字符

答案 4 :(得分:0)

警告。如果未立即找到.*?之后的文本,则正则表达式引擎将继续搜索整行,可能会跳转到下一个[youtube...]标记。通常最好使用[^\]]*?来限制括号内的搜索。

基于RoBorgs回答:

$str = preg_replace('/\[youtube=[^\]]*?v=([^\]]*?)&[^\]]*?\]/i', ...)

[^\]]将匹配除']'以外的任何字符。