Написание простого preg_replace на PHP

Я не особо разбираюсь в кодировке, но мне нужно написать простой оператор preg_replace на PHP, который поможет мне с плагином WordPress. По сути, мне нужен код, который будет искать строку, извлекать идентификатор видео и возвращать код внедрения с вставленным в него идентификатором видео.

Другими словами, я ищу это:

[youtube=https://thewikihow.com/video_VIDEO_ID_HERE&hl=en&fs=1]

И хотите заменить его на это (сохраняя идентификатор видео таким же):

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

Если возможно, я был бы бесконечно признателен, если бы вы могли объяснить, как вы использовали различные косые черты, символы вставки и звездочки Клини в шаблоне поиска, то есть перевели его с grep на английский, чтобы я мог учиться. :-)

Спасибо! Майк

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
0
4 244
5

Ответы 5

$str = preg_replace('/\[youtube=.*?v=([a-z0-9_-]+?)&.*?\]/i', 'param name = "movie" value = "http://www.youtube.com/v/&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 
         &.*?\] - the junk up to the ending ]
         /i - end the RE and make it case-insensitive for the hell of it

Чтобы не придираться, но не следует ли вам заставить его искать только буквенно-цифровые символы / символы подчеркивания в качестве значения v? Таким образом, люди не могут там оказаться глупыми.

Paolo Bergantino 10.10.2008 21:00

Хорошее объяснение атомов регулярного выражения. Тем не менее, Паоло прав - этот шаблон не должен принимать любые символы как часть идентификатора видео на YouTube.

Peter Bailey 10.10.2008 21:27

$embedString = 'youtube=https://thewikihow.com/video_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
  • [^&] сообщает ему, что он должен соответствовать любому символу Кроме амперсанду ('&')
  • * сообщает, что мы хотим от 0 до любого количества этих символов в совпадении.

Предупреждение. Если текст после .*? не найден сразу, механизм регулярных выражений продолжит поиск по всей строке, возможно, перейдя к следующему тегу [youtube...]. Часто лучше использовать [^\]]*?, чтобы ограничить поиск внутри скобок.

На основании ответа RoBorgs:

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

[^\]] соответствует любому символу, кроме ']'.

БУДЬ ОСТОРОЖЕН! Если это система в стиле BBCode с пользовательским вводом, эти два других решения сделают вас уязвимыми для XSS-атак.

У вас есть несколько способов защитить себя от этого. Попросите регулярное выражение явно запретить символы, которые могут вызвать у вас проблемы (или разрешить только те, которые действительны для идентификатора видео YouTube), или фактически дезинфицируйте ввод и используйте вместо него preg_match, что я проиллюстрирую ниже, выходя из регулярного выражения RoBorg.

<?php

$input = "[youtube=https://thewikihow.com/video_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=https://thewikihow.com/video_\"><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/&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
}

Я бы избегал регулярных выражений в этом случае, если это вообще возможно, потому что: кто гарантирует, что строка запроса в первом URL-адресе всегда будет в этом формате?

Я бы использовал parse_url($originalURL, PHP-URL-QUERY);, а затем перебирал бы возвращенный массив, находя правильную пару «имя = значение» для части v строки запроса: что-то типа:

$originalURL = 'https://thewikihow.com/video_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, непроверено.

Другие вопросы по теме