Как я могу сопоставить точную строку с переменным текстом до и после строки в PHP? - PullRequest
0 голосов
/ 16 октября 2018

Я использую небольшой скрипт проверки, который сообщает мне, когда данный URL заблокирован файлом robots.txt.

Например, существует указанный URL, например http://www.example.com/dir/test.html

Мой текущий скриптсообщает мне, заблокирован ли URL-адрес, когда в файле robots.txt есть строка, например:

Disallow: /test1.html

Но он также говорит, что URL-адрес заблокирован, когда есть такие строки, как:

Disallow: /tes

Это неправильно.

Я гуглил что-то вроде "regex точная строка" и нашел много решений для указанной выше проблемы.

Но это приводит к другой проблеме.Когда я проверяю точную строку в URL-адресе http://www.example.com/dir/test1/page.html и в файле robots.txt есть строка типа

Disallow: /test1/page.html

Мой сценарий не получает ее, поскольку ищет

Disallow: /dir/test1/page.html

И говорит: целевой файл page.html не заблокирован - но это так!

Как сопоставить точную строку с переменным текстом до и после строки?

Воткороткая версия скрипта:

/* example for $rules */
$rules = array("/tes", "/test", "/test1", "/test/page.html", "/test1/page.html", "/dir/test1/page.html")

/*example for $parsed['path']:*/
"dir/test.html"
"dir/test1/page.html"
"test1/page.html"

foreach ($rules as $rule) {
  // check if page is disallowed to us
  if (preg_match("/^$rule/", $parsed['path']))
    return false;
}

РЕДАКТИРОВАТЬ: Это целая функция:

function robots_allowed($url, $useragent = false) {
// parse url to retrieve host and path
$parsed = parse_url($url);

$agents = array(preg_quote('*'));
if ($useragent)
  $agents[] = preg_quote($useragent);
$agents = implode('|', $agents);

// location of robots.txt file
$robotstxt = !empty($parsed['host']) ? @file($parsed['scheme'] . "://" . $parsed['host'] . "/robots.txt") : "";

// if there isn't a robots, then we're allowed in
if (empty($robotstxt))
  return true;

$rules = array();
$ruleApplies = false;
foreach ($robotstxt as $line) {
  // skip blank lines
  if (!$line = trim($line))
    continue;

  // following rules only apply if User-agent matches $useragent or '*'
  if (preg_match('/^\s*User-agent: (.*)/i', $line, $match)) {
    $ruleApplies = preg_match("/($agents)/i", $match[1]);
  }
  if ($ruleApplies && preg_match('/^\s*Disallow:(.*)/i', $line, $regs)) {
    // an empty rule implies full access - no further tests required
    if (!$regs[1])
      return true;
    // add rules that apply to array for testing
    $rules[] = preg_quote(trim($regs[1]), '/');
  }
}

foreach ($rules as $rule) {
  // check if page is disallowed to us
  if (preg_match("/^$rule/", $parsed['path']))
    return false;
}

// page is not disallowed
return true;

}

URL-адрес приходит отпользовательский ввод.

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Я нашел решение, которое соответствует /test или /test/hello или /test/, но не соответствует /testosterone или /hellotest:

(?:\/test$|\/test\/)

СПеременные PHP:

if (preg_match("/(?:" . $rule . "$|" . $rule . "\/)/", $parsed['path']))

На основе вышеуказанной функции.

https://regex101.com/r/DFVR5T/3

Можно ли использовать (?:\/ ... ) или это не так?

0 голосов
/ 16 октября 2018

Попробуйте все одновременно, избегайте массива.

/(?:\/?dir\/)?\/?tes(?:(?:t(?:1)?)?(?:\.html|(?:\/page\.html)?))/

https://regex101.com/r/VxL30W/1

 (?: /?dir / )?

 /?tes 
 (?:
      (?:
           t 
           (?: 1 )?
      )?
      (?:
           \.html
        |  
           (?: /page \. html )?

      )
 )
...