php preg_replace_call: извлекать конкретные значения для последующей переустановки - PullRequest
0 голосов
/ 01 октября 2011

Ради краткости ...
Я хочу извлечь элементы из строки, поместить их в отдельный массив, заменить значения, извлеченные из строки, токенами ID'd, проанализировать строку, а затем вернуть извлеченные элементы в их исходные позиции (в правильном порядке) , (Если это имеет смысл, пропустите остальное: D)

У меня есть следующая строка;
«Мое предложение содержит URL-адреса [url] и [url], что усложняет мою жизнь».

По разным причинам я хотел бы удалить URL-адреса. Но мне нужно сохранить их место и установить их позже (после манипулирования остальной строкой).

Таким образом, я хотел бы;
«Мое предложение содержит URL-адреса [url] и [url], что усложняет мою жизнь».
стать;
«В моем предложении содержатся URL-адреса [token1fortheURL] и [token2fortheURL], что усложняет мою жизнь».

Я пытался сделать это несколько раз, разными способами. Все, что я делаю, это бью кирпичные стены и изобретаю новые ругательства!

Я использую следующий код для настройки;

$mystring = 'my sentence contains URLs to http://www.google.com/this.html and http://www.yahoo.com which makes my life difficult.';
$myregex = '/(((?:https?|ftps?)\:\/\/)?([a-zA-Z0-9:]*[@])?([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}|([0-9]+))([a-zA-Z0-9-._?,\'\/\+&%\$#\=~:]+)?)/';
$myextractions = array();

Затем я делаю preg_replace_callback;

$matches = preg_replace_callback($myregex,'myfunction',$mystring);

И у меня есть следующие функции:

function myfunction ($matches) {}

И именно здесь начинают происходить кирпичные стены. Я могу положить вещи в пустой массив извлечения - но они не доступны вне функции. Я могу обновить строку с помощью токенов, но я теряю доступ к замененным URL-адресам. Я не могу добавить дополнительные значения к вызову функции в preg_replace_callback.

Я надеюсь, что кто-то может помочь, потому что это сводит меня с ума.


UPDATE:

На основании решения, предложенного @Lepidosteus, Я думаю, что у меня работает следующее?

$mystring = 'my sentence contains URLs to http://www.google.com/this.html and http://www.yahoo.com which makes my life difficult.';
$myregex = '/(((?:https?|ftps?)\:\/\/)?([a-zA-Z0-9:]*[@])?([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}|([0-9]+))([a-zA-Z0-9-._?,\'\/\+&%\$#\=~:]+)?)/';
$tokenstart = ":URL:";
$tokenend = ":";


function extraction ($myregex, $mystring, $mymatches, $tokenstart, $tokenend) {
$test1 = preg_match_all($myregex,$mystring,$mymatches);
$mymatches = array_slice($mymatches, 0, 1);
$thematches = array();

foreach ($mymatches as $match) {
    foreach ($match as $key=>$match2) {
        $thematches[] = array($match2, $tokenstart.$key.$tokenend);
    }
}


return $thematches;
}
$matches = extraction ($myregex, $mystring, $mymatches, $tokenstart, $tokenend);
echo "1) ".$mystring."<br/>";
// 1) my sentence contains URLs to http://www.google.com/this.html and http://www.yahoo.com which makes my life difficult.



function substitute($matches,$mystring) {
foreach ($matches as $match) {
    $mystring = str_replace($match[0], $match[1], $mystring);
}
return $mystring;
}
$mystring = substitute($matches,$mystring);
echo "2) ".$mystring."<br/>";
// 2) my sentence contains URLs to :URL:0: and :URL:1: which makes my life difficult.


function reinsert($matches,$mystring) {
foreach ($matches as $match) {
    $mystring = str_replace($match[1], $match[0], $mystring);
}
return $mystring;
}
$mystring = reinsert($matches,$mystring);
echo "3) ".$mystring."<br/>";
// 3) my sentence contains URLs to http://www.google.com/this.html and http://www.yahoo.com which makes my life difficult.

Это похоже на работу?

1 Ответ

1 голос
/ 01 октября 2011

Ключом к решению вашей проблемы здесь является сохранение списка URL-адресов во внешнем контейнере, к которому могут обращаться ваши обратные вызовы и ваш основной код для внесения необходимых вам изменений.Чтобы запомнить ваши URL-адреса, мы будем использовать пользовательский токен в строке.

Обратите внимание, что для доступа к контейнеру я использую замыкания , если вы по какой-то причине не можете использовать php 5.3нужно будет заменить их другим способом доступа к контейнеру $ url_tokens из обратного вызова, что не должно быть проблемой.

<?php
// the string you start with

$string = "my sentence contains URLs to /4932822/php-pregreplacecall-izvlekat-konkretnye-znacheniya-dlya-posleduyschei-pereustanovki and http://www.google.com/ which makes my life difficult.";

// the url container, you will store the urls found here

$url_tokens = array();

// the callback for the first replace, will take all urls, store them in $url_tokens, then replace them with [[URL::X]] with X being an unique number for each url
//
// note that the closure use $url_token by reference, so that we can add entries to it from inside the function

$callback = function ($matches) use (&$url_tokens) {
  static $token_iteration = 0;

  $token = '[[URL::'.$token_iteration.']]';

  $url_tokens[$token_iteration] = $matches;

  $token_iteration++;

  return $token;
};

// replace our urls with our callback

$pattern = '/(((?:https?|ftps?)\:\/\/)?([a-zA-Z0-9:]*[@])?([a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}|([0-9]+))([a-zA-Z0-9-._?,\'\/\+&amp;%\$#\=~:]+)?)/';

$string = preg_replace_callback($pattern, $callback, $string);

// some debug code to check what we have at this point

var_dump($url_tokens);
var_dump($string);

// you can do changes to the url you found in $url_tokens here

// now we will replace our previous tokens with a specific string, just as an exemple of how to re-replace them when you're done

$callback_2 = function ($matches) use ($url_tokens) {
  $token = $matches[0];
  $token_iteration = $matches[1];

  if (!isset($url_tokens[$token_iteration])) {
    // if we don't know what this token is, leave it untouched
    return $token;
  }

  return '- there was an url to '.$url_tokens[$token_iteration][4].' here -';
};

$string = preg_replace_callback('/\[\[URL::([0-9]+)\]\]/', $callback_2, $string);

var_dump($string);

, которые дают этот результат при выполнении:

// the $url_tokens array after the first preg_replace_callback
array(2) {
  [0]=>
  array(7) {
    [0]=>
    string(110) "/4932822/php-pregreplacecall-izvlekat-konkretnye-znacheniya-dlya-posleduyschei-pereustanovki"
    [1]=>
    string(110) "/4932822/php-pregreplacecall-izvlekat-konkretnye-znacheniya-dlya-posleduyschei-pereustanovki"
    [2]=>
    string(7) "http://"
    [3]=>
    string(0) ""
    [4]=>
    string(17) "stackoverflow.com"
    [5]=>
    string(0) ""
    [6]=>
    string(86) "/questions/7619843/php-preg-replace-call-extract-specific-values-for-later-reinsertion"
  }
  [1]=>
  array(7) {
    [0]=>
    string(22) "http://www.google.com/"
    [1]=>
    string(22) "http://www.google.com/"
    [2]=>
    string(7) "http://"
    [3]=>
    string(0) ""
    [4]=>
    string(14) "www.google.com"
    [5]=>
    string(0) ""
    [6]=>
    string(1) "/"
  }
}
// the $string after the first preg_replace_callback
string(85) "my sentence contains URLs to [[URL::0]] and [[URL::1]] which makes my life difficult."

// the $string after the second replace
string(154) "my sentence contains URLs to - there was an url to stackoverflow.com here - and - there was an url to www.google.com here - which makes my life difficult."
...