소스 코드의 " "로 묶인 스트링만 뽑아내는 정규표현

netbsd00의 이미지

코드에서 스트링만 뽑아내기 위해
정규표현식을 공부한 후 나름대로
적용을 시켜 보았습니다.

grep -o '\"[^,\s]*\"' filename.c

얼핏 봐서는 만족스러운 결과인듯 했으나
좀 살펴보니 제대로 뽑아지지가 않았군요.
제가 구현한 식에서 어디가 잘못되었는지..
제대로 뽑을려면 어떻게 해야 하는지 알고싶습니다.
여러분들의 도음을 기다리겠습니다.

미리 감사드립니다.

랜덤여신의 이미지

일단... 명령행을 ' 로 감싸셨으니 \ 는 쓰실 필요가 없을 것 같구요,
[^] 집합 안에 " 도 추가해보세요~

혹시 펄 정규식이 사용 가능하다면, (grep 에서는 -P 옵션)
"(.*?)" 을 쓰는 것이 더 나을 것 같습니다.

익명 사용자의 이미지

grep "\"\(\\.\|[^\\\"]\)*\"" *.c

참고1) regular expression기술에서 다음 문자는 escape sequence가 되어야 합니다.
?, +, {, |, (, )
참고2) 그래서, 제가 string_literal(즉 "..." 로 둘러쌓인 문자열)을 판별할때,
사용했던 레귤라 익스프레션(Lex용, flex...)을 다음...
\"(\\.|[^\\"])*\"

을 다음으로 바꿨습니다.

\"\(\\.\|[^\\\"]\)*\"

다음은 grep에 적용하기 위해 앞뒤에 ""를 추가.

익명 사용자의 이미지

참, RedHat 9
grep (GNU grep) 2.5.1 버전에서 였습니다.

lsj0713의 이미지

PHP에서 펄 스타일의 preg 계열 정규식에 쓰는 코드에다가 C언어가 아니라 검색문자열에서 "...", '...', ...를 걸러내는 코드라서 약간 다를 수도 있고, 때에 따라서는 불가능할 수도 있겠습니다만 참고가 되었으면 좋겠습니다.

$pattern =
    "/" .
    "\"((?:\\\\\\\\|\\\\\"|[^\"])+?)\"|" .
    "\'((?:\\\\\\\\|\\\\\'|[^\'])+?)\'|" .
    "([^\s]+)" .
    "/i";

preg_match_all($pattern, $s_str, $out, PREG_SET_ORDER);

소스 코드가 무슨 언어인지는 모르겠지만 일단 C라 가정하면, 다음과 같은 상황들에 대한 대비가 필요합니다.

Quote:

"\\"
"\\\\"
"\""
"\\\"\\"
"\"\"\""
"\\\\\\\\\\"

맨 처음의 코드 중에서 " "로 둘러싸인 문자열을 걸러내는 패턴만 다시 봅시다. 이 패턴 자체도 문자열로 되어 있으며, 각각의 \에는 escape sequence 처리가 되어 있음을 주의합시다.

    "\"((?:\\\\\\\\|\\\\\"|[^\"])+?)\""

일단 문자열은 " 와 "로 둘러싸여 있습니다.

"\" ... \""

이 따옴표 안에 어떤 문자들이 1개 이상 들어갈 수 있을 것입니다. 우리가 필요한 것은 바로 이 부분일 것이므로 일단 괄호로 둘러쳐 줍시다. + 뒤에 붙은 ?는 perl 스타일 정규 표현식에서 지원하는 확장으로, .+?의 경우에는 최대한 잘라먹기 규칙(혹은 greedy?)을 적용하지 않도록 해 줍니다. (근데 이 상황에서 꼭 ?를 붙여야 하는지 아닌지는 확신하지 못하겠습니다. 일단은 그대로 붙여놓겠습니다.)

"\" (... )+?) \""

여기서 ...에는 escape sequence와 개행문자가 아닌 문자, 이렇게 두가지 패턴이 올 수 있습니다. 맨 처음에 C 소스 코드라 가정하였으니 관련 문법을 참고하자면...

Quote:

escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
universal-character-name
simple-escape-sequence: one of
\' \" \? \\
\a \b \f \n \r \t \v
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit

이걸 정규식으로 바꾸면 다음과 같이 됩니다. 공백은 보기 편하게 하기 위해 넣은 것이므로 나중에 지워 주십시오.

(?:
    (?: \\\' | \\\" | \\? | \\\\ | \\a | \\b | \\f | \\n | \\r | \\t | \\v ) |
    (?: \\[0-7]{1,3} ) |
    (?: \\x[0-9a-fA-F]? ) |
    .
) +?

위의 패턴을 그 위에서 제시한 "\" (... )+?) \"" 와 결합하면 될 것입니다. 다만 질문자께서는 php가 아니라 grep에서 쓰기를 원하시므로 여기에 다시 탈출문자인 /를 적당히 붙이거나 줄여야 할 것입니다.

정확히 확인해보지 않고 대충 써서 답변함을 양해해 주십시오. 도움이 되었기를 바라며 그러면 이만...

cinsk의 이미지

예전에 저도 비슷한 것을 쉽게 얻어내는 방법이 없을까 했는데.. 쉽지가 않더군요..

가장 큰 문제가 다음과 같이 backslash 뒤에 newline이 나오는 것을 처리하는 문제인 것 같습니다:

char *p = "hello, \
world";

또는 아예 newline이 들어있는 것들...

char *p = "hello, 
world";

GNU grep이면.. Perl의 regexp 처리 방식을 써서
다음과 같이 했더니.. 괜찮은 결과가 나오는 것 같군요.

혹시 더 좋은 방법이 있으면 알려주시기 바랍니다.

grep -P -o '\"(.|[\n]|\\[\n])*\"' tmp.txt
mr.lee의 이미지

저도 첨에 programming language에서 따옴표사이를 잡아내는게 까다롭더군요...

요즘 제가 진행하고 있는 플젝에서 사용하는 regex입니다. 참고하시구요. perl 5 문법입니다.

#define REGEX_COMMENT_S "(?xs: // .*? [\n] )"

#define REGEX_COMMENT_M "(?xs: / \\* .*? \\* / )"

#define REGEX_DOUBLE_QUOTA "(?x-s: (?<! \\\\) \" .*? [^\\\\] \" )"

댓글 달기

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