php에서 substr과 backreference?

logout의 이미지

안녕하세요.

phpBB에서.... 글을 올렸을 때 url이 너무 길어지는 것이 보기 싫어서 난생처음 잠깐 php 소스코드를 보고 있는데요. substr 함수를 쓰는데 문제가 생겨서 질문을 적어봅니다. 우선, phpBB에서는 올라온 글에 url이 포함되면 preg_replace 함수를 이용해서 url 앞뒤로 a 태그를 추가합니다. 다음은 그 부분 소스 코드이구요. $ret에는 사용자가 올린 글이 들어가 있습니다.

 $ret = preg_replace("#(^|[\n ])([\w]+?://[^ \"\n\r\t<]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);

이것을 다음과 같이 쪼갰습니다. url 디스플레이를 할 때는 앞에서 10자만 출력하고 뒤에는 생략의 표시로 .........을 붙이는 것이죠.

$url_pattern = "#(^|[\n ])([\w]+?://[^ \"\n\r\t<]*)#is";
$ret = preg_replace($url_pattern, "\\1<a href=\"\\2\"target=\"_blank\">". substr("\\2", 0, 10) . "......... </a>", $ret);

그런데 여기서 문제는 substr 함수를 쓰니까 back reference인 "\\2"가 그냥 스트링으로 인식이 된다는 것입니다. 그리고 "\\2"가 제대로 정규식에서 매칭된 url로 바뀌는 경우는 substr 함수가 동작을 제대로 하지 않고 "\\2"에 저장된 전체 url 스트링을 모두 출력해 버리는 문제가 있습니다. back reference "\\2"에 저장된 값을 처음 10자만 끄집어 내려면 어떤 방법을 쓰면 될까요?

nohmad의 이미지

함수의 인수로 넘어간 문자열은 해석이 되어버려서 정규식의 백레퍼런스의 의미를 상실하게 되므로, 정규식을 고치지 않고, 백레퍼런스 값만을 스트링 함수로 조작하는 것은 안될 것 같습니다.

꼭 하나의 식으로 평가할 필요가 없다면 preg_match로 나눠서 처리하면 되지 않을까요?

$ret = preg_match($url_pattern, $ret, $match);

이렇게 한 뒤에 print_r($match)를 해보면, 어떻게 붙여서 써야할지 감이 오실 것 같네요.

행복한고니의 이미지

현재 상태에서 간단하게 생각하시려면... preg_replace_callback 을 사용해보세요.

__________________________________
나는 세상에서 가장 중요한 사람이다.

익명 사용자의 이미지

logout wrote:
안녕하세요.

phpBB에서.... 글을 올렸을 때 url이 너무 길어지는 것이 보기 싫어서 난생처음 잠깐 php 소스코드를 보고 있는데요. substr 함수를 쓰는데 문제가 생겨서 질문을 적어봅니다. 우선, phpBB에서는 올라온 글에 url이 포함되면 preg_replace 함수를 이용해서 url 앞뒤로 a 태그를 추가합니다. 다음은 그 부분 소스 코드이구요. $ret에는 사용자가 올린 글이 들어가 있습니다.

 $ret = preg_replace("#(^|[\n ])([\w]+?://[^ \"\n\r\t<]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);

이것을 다음과 같이 쪼갰습니다. url 디스플레이를 할 때는 앞에서 10자만 출력하고 뒤에는 생략의 표시로 .........을 붙이는 것이죠.

$url_pattern = "#(^|[\n ])([\w]+?://[^ \"\n\r\t<]*)#is";
$ret = preg_replace($url_pattern, "\\1<a href=\"\\2\"target=\"_blank\">". substr("\\2", 0, 10) . "......... </a>", $ret);

그런데 여기서 문제는 substr 함수를 쓰니까 back reference인 "\\2"가 그냥 스트링으로 인식이 된다는 것입니다. 그리고 "\\2"가 제대로 정규식에서 매칭된 url로 바뀌는 경우는 substr 함수가 동작을 제대로 하지 않고 "\\2"에 저장된 전체 url 스트링을 모두 출력해 버리는 문제가 있습니다. back reference "\\2"에 저장된 값을 처음 10자만 끄집어 내려면 어떤 방법을 쓰면 될까요?

$url_pattern = "#(^|[\n ])([\w]+?://[^ \"\n\r\t<]*)#eis";
$ret = preg_replace($url_pattern, "'\\1<a href=\"\\2\" target=\"_blank\">'.substr('\\2', 0, 10).'......... </a>'", $ret);
wkpark의 이미지

처음 10자는 너무 부족한 듯 하군요. 인쇄같은 걸 할 때는 url을 다 표시하는게 나을것이고, 처음 몇자 + 중간 생략 + 마지막 몇자와 같이 단축할 수도 있겠고,

유연한 처리를 위해서는 preg_replace_callback()을 써야할 듯.

온갖 참된 삶은 만남이다 --Martin Buber

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.