2009-09-19 4 views
0

PHP preg_replace() 솔루션을 찾고 있는데 이미지 링크를 찾고 해당 이미지 태그로 바꿉니다.<a>을 각각 <img>으로 바꿀 수있는 정규 표현식

찾기 :

<a href="http://www.domain.tld/any/valid/path/to/imagefile.ext">This will be ignored.</a> 

가 교체 : 프로토콜은 HTTP이어야한다

<img src="http://www.domain.tld/any/valid/path/to/imagefile.ext" alt="imagefile" /> 

이 : //는 .ext를 유효한 이미지 포맷을 (수 있어야한다 .JPG, .JPEG. gif, .png, .tif)이고 기본 파일 이름은 alt = ""값이됩니다.

저는 preg_replace()가 작업에 적합한 함수라는 것을 알고 있습니다. 그러나 정규 표현식을 빨아 들여서 어떤 도움도 크게 받으실 수 있습니다! 감사!

답변

7

아, 제 일상적인 DOM 연습입니다. DOM을 사용하여 HTML을 구문 분석하고 HTML 속성과 같은 문자열을 구문 분석하는 정규식을 사용해야합니다.

참고 : 나는 확실히 어떤 마법사 :)으로 따라 개선 할 수있는 몇 가지 기본적인 정규 표현식에이

참고 # 2 : 당신은 HREF가있는 경우 철저하게 확인 컬 같은 것을 사용할 수있는 추가 오버 헤드가 될 수 있지만 실제 이미지는 HEAD 요청을 보내고 Content-Type을보고 있지만이 경우 80-90 %에서 작동합니다.

<?php 

$content = ' 

<a href="http://www.domain.tld/any/valid/path/to/imagefile.ext">This will be ignored.</a> 
<br> 

<a href="http://col.stb.s-msn.com/i/43/A4711309495C88F8CD154C99FCE.jpg">this will not be ignored</a> 

<br> 

<a href="http://col.stb.s-msn.com/i/A0/8E9A454F701E4F5F89E58E14B532C.jpg">bah</a> 
'; 

$dom = new DOMDocument(); 
$dom->loadHTML($content); 

$anchors = $dom->getElementsByTagName('a'); 

$i = $anchors->length-1; 

$protocol = '/^http:\/\//'; 
$ext = '/([\w+]+)\.(?:gif|jpg|jpeg|png)$/'; 

if (count($anchors->length) > 0) { 
    while($i > -1) { 
    $anchor = $anchors->item($i); 
    if ($anchor->hasAttribute('href')) { 
     $link = $anchor->getAttribute('href'); 

     if ( 
     preg_match ($protocol , $link) && 
     preg_match ($ext, $link) 
     ) { 
     //echo 'replacing this one.'; 
     $image = $dom->createElement('img'); 

     if (preg_match($ext, $link, $matches)) { 
      if (count($matches)) { 
      $altName = $matches[1]; 
      $image->setAttribute('alt', $altName); 
      } 
      $image->setAttribute('src', $link); 
      $anchor->parentNode->replaceChild($image, $anchor); 
     } 
     } 

    } 
    $i--; 
    } 
} 

echo $dom->saveHTML(); 
+0

을 .. 이 작업은 preg_replace를 사용하여 수행 할 수 있습니다. 내 대답 좀 봐. – Seb

+4

정규식 솔루션이 너무 실패하기 쉽기 때문에 DOM을 고수 하겠지만 감사합니다. –

+2

DOM 솔루션은 원하는 DOM 연산을 수행 할 수있는만큼 훨씬 유연합니다. 정규 표현식으로는 제한적입니다. –

10

축하합니다. 백만 분의 1 고객이 스택 오버플로에 HTML을 정규식으로 구문 분석하는 방법을 묻습니다!

[X] [HT] ML은 정규 언어가 아니며 신뢰할 수있는 정규식으로 파싱 할 수 없습니다. HTML 파서를 사용하십시오. PHP 자체에서 DOMDocument을 제공하거나 simplehtmldom을 선호 할 수 있습니다.

덧붙여 말하자면 URL을보고 어떤 파일인지 알 수 없습니다. JPEG가 확장자로 .jpeg를 가져야하는 이유는 없습니다. 사실 '.jpeg'확장자를 가진 파일이 실제로 JPEG 일 것이라는 보장은 없습니다. 확실한 유일한 방법은 리소스 (예 : HEAD 요청 사용)를 가져 와서 Content-Type 헤더를 살펴 보는 것입니다.

+1

-1 이것은 문제를 해결하지 못합니다. 아무도 HTML을 정규 표현식으로 파싱하는 것에 신경을 쓰지 않습니다. 이미지를 검증하고 마크 업을 만드는 경우 모든 것이 잘 작동한다는 것이 확실 할 수 있습니다. – Seb

+1

실제로. 그러나 질문자는 마크 업 형식이 자신의 통제하에 있다고 명시하지 않았습니다. – bobince

+0

도 아니다라고 그는 말하지 않았다. 당신은 문맥에 대해 아무것도 모른다. 그래서 이것은 대답이 아니라 질문에 대한 주석이어야한다. – Seb

1

난이 더 유연 비 greddy 정규식을 사용하는 것이 좋습니다 것입니다 :

<a[^>]+?href=\"(http:\/\/[^\"]+?\/([^\"]*?)\.(jpg|jpeg|png|gif))[^>]*?>[^<]*?<\/a> 

그리고 (PHP 테스트 코드 포함) 좀 더 복잡한 정규식 희망 검보을 기쁘게합니다 :) 너무 긴

<?php 
$test_data = <<<END 
<a blabla="asldlsaj" alksjada="aslkdj" href="http://www.domain.tld/any/valid/path/to/imagefile.jpg" lkjasd=""asdlaskjd>This will be ignored.</a> 
Lorem ipsum.. 
<a blabla=asldlsaj alksjada="aslkdj" href="http://www.domain.tld/any/valid/path/to/imagefile.jpg" lkjasd=""asdlaskjd>This will be ignored.</a> 
<a lkjafs='asdsa> ' blabla="asldlksjada=>"aslkdj" href="http://www.domain.tld/any/valid/path/to/imagefile.jpg" lkjasd=""asdlaskjd>This will be ignored.</a> 
<a blabla="ajada="aslk href="http://www.domain.tld/any/valid/path>/to/imagefile.jpg" lkjasd>asdlaskjd>This will be ignored.</a> 
<a blabla="asldlsaj>" aslkdj href="http://www.domain.tld/any/valid/path/ to/imagefile.jpg" lkjasd=""asdlaskjd>This will be ignored.</a> 
Something: 
<a blabla='asldls<ajslkdj' href="http://www.domain.tld/any/valid'/path/to/imagefile.jpg" lkjasd=""asdlaskjd>This will be ignored.</a> 
<a blabla= asldlsadj href="http://www.domain.tld/any/valid/path/to/imagefile.jpg" lkjasd>This will be ignored.</a> 
<a blabla="asldlsaj" alksjslkdj" href='http://www.domain.tld/any/valid/path/to/imagefile.jpg' lkjasdskjd>This will be ignored.</a> 
Something else... 
<a blabla="asldlsaj" alksjslkdj" href='http://www.domain.tld/any/valid/path/to/imagefile.jpg' lkjasdskjd>This will be ignored.</a> 
<a blabla="asldlsaj" alksjada="aslkdj" href=http://www.domain.tld/any/valid/path/to/imagefile.jpg lkjdlaskjdll> be ignored.</a> 
END; 
$regex = "/<a\s(\s*\w+(\s*=\s*(\".*?\"|'.*?'|[^'\">\s]+))?)+?\s+href\s*=\s*(\"(http:\/\/[^\"]+\/(.*?)\.(jpg|jpeg|png|gif))\"|'(http:\/\/[^']+\/(.*?)\.(jpg|jpeg|png|gif))'|(http:\/\/[^'\">\s]+\/([^'\">\s]+)\.(jpg|jpeg|png|gif)))\s(\s*\w+(\s*=\s*(\".*?\"|'.*?'|[^'\">\s]+))?)+>[^<]*?<\/a>/i"; 
$replaced = preg_replace($regex, '<img src="$5$8$11" alt="$6$9$12" />', $test_data); 

echo '<pre>'.htmlentities($replaced); 
?> 
+0

속성 값은 리터럴'>'을 포함 할 수 있습니다. – Gumbo