Mit preg_match interne & externe Links trennen

kramoo

Mitglied
Habe die Aufgabe aus einer langen Liste interne und externe Links heraus zu filtern.

Code:
z.B. Liste (als String oder array):
[ url]http://blog.test.net[ /url]
[ url]http://test.net/dyd[ /url]
[ url]http://www.test.net[ /url]
[ url]http://example.com/test[ /url] 
...

Möchte alle Links die nicht zur Url 'http://test.net oder 'http://www.test.net passen.
Also 'http://blog.test.net und 'http://example.com/test währen hier richtig.

Bis jetzt sieht mein Regulärer Ausdruck so aus:
PHP:
$suchstring = '(http://test.net|http://www.test.net)'; 
$ExtLinks = preg_match_all("#$suchstring#i",$links,$treffer);
Denke da gibs aber noch Probleme. Wie sollte dieser aussehen damit nur am Anfang der URL gesucht wird und nur die nicht übereinstimmenden zurückgeliefert werden?

Ziel ist es also alle externen Links und dazu gehören auch subdomains zu bekommen. Vielleicht gibt es auch einen besseren weg?
 
Hallo kramoo,

mit einem negativen look ahead in dem RegEx kannst Du das machen:
PHP:
$links = '[ url]http://blog.test.net[ /url]
[ url]http://test.net/dyd[ /url]
[ url]http://www.test.net[ /url]
[ url]http://example.com/test[ /url]
[ url]http://test.test.net[ /url]';

$extLinks = preg_match_all( '#\[url\](http://(?!www\.test\.net|test\.net)[^\]]*?)\[/url\]#i', $links, $treffer );

echo '<pre>';
var_dump( $extLinks );
var_dump( $treffer );
echo '</pre>';

Ausgabe:
Code:
int(3)
array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(31) "[ url]http://blog.test.net[ /url]"
    [1]=>
    string(34) "[ url]http://example.com/test[ /url]"
    [2]=>
    string(31) "[ url]http://test.test.net[ /url]"
  }
  [1]=>
  array(3) {
    [0]=>
    string(20) "http://blog.test.net"
    [1]=>
    string(23) "http://example.com/test"
    [2]=>
    string(20) "http://test.test.net"
  }
}

Gruß
 
Zuletzt bearbeitet:
Keine Ahnung ob das [url ][/url ] jetzt dazu gehören sollte oder nicht. Aber das pattern geht auch etwas kürzer.
PHP:
$arr = array("http://blog.test.net",
				"http://test.net/dyd",
				"http://www.test.net",
				"http://example.com/test");

$pattern = '#(http://(?!(?:www\.)?test\.net).*)#i';				

foreach($arr as $item)
{	
	preg_match($pattern, $item, $matches);
	var_dump($matches);
}

Code:
array
  0 => string 'http://blog.test.net' (length=20)
  1 => string 'http://blog.test.net' (length=20)

array
  empty

array
  empty

array
  0 => string 'http://example.com/test' (length=23)
  1 => string 'http://example.com/test' (length=23)
 
Zuletzt bearbeitet:
Klar geht es kürzer, in meinem Fall würde es den $treffer-Array aber aufblähen.

ps: Mit .* wäre ich vorsichtig.
 
Nö. Warum sollte es.
Gut, jetzt mit der non capturing group würde es den Array nicht mehr aufblähen.

Wenn du damit auf Regex DoS anspielst dann ist das 1. in diesem Fall nicht zutreffend und 2. Sowieso nur dann relevant wenn gegen Usereingaben geprüft wird (was in diesem Fall nicht klar ersichtlich ist).
Ich meinte eigentlich, dass dieser Ausdruck zu gierig ist. Wenn dann lieber .*? oder mit dem modifier U damit der Ausdruck ungreedy ist. Wobei, wenn die URL-Tags dazugehören, dann besser etwas in der Form [^\[]+.

PHP:
$links = '[ url]http://blog.test.net[ /url]
[ url]http://test.net/dyd[ /url]
[ url]http://www.test.net[ /url]
[ url]http://example.com/test[ /url]
[ url]http://test.test.net[ /url]';
 
$extLinks = preg_match_all( '#\[url\](http://(?!(?:www\.)?test\.net)[^\]]+)\[/url\]#i', $links, $treffer );
 
echo '<pre>';
var_dump( $extLinks );
var_dump( $treffer );
echo '</pre>';

Gruß
 
Zurück