[PHP] PCRE 정규표현식 질문입니다

ecstatic의 이미지

PCRE 정규표현식 질문드립니다.
PHP로 짜고 있는데, 잘 안되네요...

예제 - 이전)
http://xx777.mizc.com/bbs/data/picture/전시1.jpg
<img src="http://xx777.mizc.com/bbs/data/picture/전시1.jpg">
<a href=http://xx777.mizc.com/bbs/data/picture/전시1.jpg>http://xx777.mizc.com/bbs/data/picture/전시1.jpg</a>

예제 - 실행 후)
<a href="http://xx777.mizc.com/bbs/data/picture/전시1.jpg" target="_blank">http://xx777.mizc.com/bbs/data/picture/전시1.jpg</a>
<img src="<a href="http://xx777.mizc.com/bbs/data/picture/전시1.jpg" target="_blank">http://xx777.mizc.com/bbs/data/picture/전시1.jpg</a>">
<a href=<a href="http://xx777.mizc.com/bbs/data/picture/전시1.jpg" target="_blank">http://xx777.mizc.com/bbs/data/picture/전시1.jpg</a>><a href="http://xx777.mizc.com/bbs/data/picture/전시1.jpg" target="_blank">http://xx777.mizc.com/bbs/data/picture/전시1.jpg</a></a>

이렇게 나오죠. 사실 예상은 했는데
태그를 쓴것과 안 쓴것을 어떻게 처리할까 고민입니다.
제 생각은, 태그 쓰기전에 반드시 들어가는 조건이
= , =' , ="
이 3개의 character이 들어가잖아요, 이것이 들어가면 부정하고 싶은데
마음먹은대로 결과가 안나오네요

다시한번 설명하자면, 제가 원하는 결과는
태그를 쓰지 않은 URL만 자동링크 시키고 싶은데 말이죠

일단 소스
function autolink($str) {
$regex['prot'] = "(http|https|ftp|telnet|gopher|news|nntp|rtsp|mms|ed2k)(://)";
$regex['path'] = "(([xA1-xFEa-z0-9:_-]+.[xA1-xFEa-z0-9,:;&#=_~%\[\]?\/.,+-]+)([.]*[\/a-z0-9\[\]]|=[xA1-xFE]+))";
$regex['url'] = $regex['prot'].$regex['path'];

$src = "/([=]['|\"]){0}".$regex['url']."/i";
$tar = "<a href=\"\\2\\3\\4\" target=\"_blank\">\\2\\3\\4</a>";

$str = preg_replace($src,$tar,$str);
return $str;
}

음 일단 부정하는 쪽의 정규식이 잘못된것 같은데
잘 모르겠군요.

익명 사용자의 이미지

두가지 경우를 다 검색해서, 'e' modifier를 이용해서 조건문으로 한쪽 경우일 경우에만 치환을 해주면 됩니다. perl에서는 흔히 쓰이는 테크닉인데... php에선 좀 여러모로 불편해서 잘 쓰이지 않습니다.. 가장 골때리는게 큰따옴표 or 작은따옴표 or 슬래쉬 escape 시키는 겁니다. 여러번 다양한 문자열(특히 큰따옴표 작은따옴표 슬래쉬가 포함된 문자열들)을 가지고 다각도로 테스트를 해서 이해하지 않으면 버그 만들기 쉽상이죠.

$pattern_a = 대충 <a href="..."> 이런거...
$pattern_b = http:// 이런거...
$pattern = "/(A)|(B)/e";
$replace = "\"\\\1\" != \"\" ? \"\\\1\" : \"<a href=\\\"\\\\2\\\">\\\\2</a>\"";
$str = preg_replace($pattern, $replace, $str);

그리고 패턴은 속도와 범용성을 생각해서, 적당히 느슨하게 만드는 것이 좋습니다. url 패턴은 전 다음과 같이 씁니다(방금 생각나는대로 적은거라 정확하진 않습니다..

http://[^ \r\n\t]+

혹은

http://[^ \r\n\t/]+(/[^ \r\n\t]*)?

공백이 나오기 전까지 url로 보는 거죠. 사용자들이 한글로 된 URL 등도 많이 쓰기 때문에, RFC 참고해서 엄밀하게 만들면 여러가지 현실적인 문제점들에 부딪칩니다.

송효진의 이미지

'(?<!=)(?<![\'"])'.$regex['url'].'/i';

php 매뉴얼에 pcre 로 찾으면 나오는 문서에서
(?=) (?!) (?<=) (?<!) 를 보세요.

(?<![\'"]?) <- 이런건 안됩니다. 문자열 길이가 고정되야 되요.

송효진의 이미지

prot 에 // 는 탈출시켜야겠군요.

ecstatic의 이미지

그런데 문제가

http://excf.com/eboard/view.php

여기 보시면 아시겠지만,
a 태그로 둘러싼 URL까지 적용이 됩니다.

음 :shock:
골치아프군요
계속 연구해봐야 할듯.

그래도 감사합니다 :D

goverment issue

ecstatic의 이미지

감사합니다 금방 끝났군요
:oops:

goverment issue

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.