문제

C 소스 코드에서 문자열을 제거하는 프로그램을 알려줄 수 있는 사람이 있나요?예

#include <stdio.h>
static const char *place = "world";
char * multiline_str = "one \
two \
three\n";
int main(int argc, char *argv[])
{
        printf("Hello %s\n", place);
        printf("The previous line says \"Hello %s\"\n", place);
        return 0;
}

된다

#include <stdio.h>
static const char *place = ;
char * multiline_str = ;
int main(int argc, char *argv[])
{
        printf(, place);
        printf(, place);
        return 0;
}

내가 찾고 있는 것은 매우 유사한 프로그램이다. 스트립 cmt주석이 아닌 문자열을 제거하고 싶습니다.

내가 이미 개발 된 프로그램을 찾고 있고 편리한 정규 표현이 아니라 이미 개발 된 프로그램을 찾고있는 이유는 모든 코너 케이스 (문자열 내 인용문, 멀티 라인 문자열 등)를 고려하기 시작할 때 일반적으로 그보다 훨씬 더 복잡하기 시작하기 때문입니다. 먼저 나타납니다.그리고 RES가 달성 할 수있는 것에 제한이 있습니다.이 작업에는 불가능하다고 생각합니다.당신이 가지고 있다고 생각한다면 극도로 강력한 정규식을 자유롭게 제출하세요. 하지만 순진한 생각은 하지 마세요. sed 's/"[^"]*"//g' 제안처럼요.

(주석 내의 문자열(끝나지 않을 수도 있음)을 특별히 처리할 필요가 없습니다. 해당 문자열이 먼저 제거됩니다.)

줄 바꿈이 포함된 여러 줄 문자열에 대한 지원은 중요하지 않지만(적법한 C는 아님) 끝에 \로 끝나는 여러 줄에 걸쳐 있는 문자열은 지원되어야 합니다.

이거랑 거의 똑같네요 일부 다른 질문, 그러나 어떤 도구에 대한 참조도 찾지 못했습니다.

도움이 되었습니까?

해결책

당신은 그것을 다운로드 할 수 있습니다 stripcmt에 대한 소스 코드 (.tar.gz -5kb). 사소하게 작으며 스트라이핑 문자열에 적응하기가 너무 어렵지 않아야합니다 ( GPL 아래에 출시되었습니다).

C 문자열에 대한 공식 어휘 언어 규칙을 조사 할 수도 있습니다. 나는 찾았다 이것 매우 빨리하지만 결정적이지 않을 수도 있습니다. 문자열을 다음과 같이 정의합니다.

stringcon ::= "{ch}", where ch denotes any printable ASCII character (as specified by isprint()) other than " (double quotes) and the newline character.

다른 팁

C(및 대부분의 다른 프로그래밍 언어)의 모든 토큰은 "일반"입니다.즉, 정규식으로 일치시킬 수 있습니다.

C 문자열에 대한 정규식:

"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"

정규식은 이해하기가 그리 어렵지 않습니다.기본적으로 문자열 리터럴은 다음을 묶는 큰따옴표 쌍입니다.

  • 특수하지 않은(따옴표가 아닌/백슬래시/개행 문자) 문자
  • 이스케이프는 백슬래시로 시작하고 다음 중 하나로 구성됩니다.
    • 간단한 이스케이프 문자
    • 1~3개의 8진수
    • x 및 1개 이상의 16진수

이는 C89/C90 사양의 섹션 6.1.4 및 6.1.3.4를 기반으로 합니다.C99에 다른 것이 들어와도 이를 포착할 수는 없지만 해결하기 어렵지는 않습니다.

다음은 문자열 리터럴을 제거하여 C 소스 파일을 필터링하는 Python 스크립트입니다.

import re, sys
regex = re.compile(r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"''')
for line in sys.stdin:
  print regex.sub('', line.rstrip('\n'))

편집하다:

위의 내용을 게시한 후 모든 C 토큰이 일반 토큰인 것은 사실이지만 모든 것을 토큰화하지 않으면 문제가 발생할 수 있다는 생각이 들었습니다.특히, 다른 토큰이어야 하는 곳에 큰따옴표가 나타나면 우리는 정원 경로로 안내될 수 있습니다.주석은 이미 제거되었다고 말씀하셨는데, 우리가 정말로 걱정해야 할 유일한 것은 문자 리터럴입니다(그러나 제가 사용할 접근 방식은 주석 처리를 위해 쉽게 확장될 수 있습니다).다음은 문자 리터럴을 처리하는 보다 강력한 스크립트입니다.

import re, sys
str_re = r'''"([^"\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))*"'''
chr_re = r"""'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|x[0-9a-fA-F]+))'"""

regex = re.compile('|'.join([str_re, chr_re]))

def repl(m):
  m = m.group(0)
  if m.startswith("'"):
    return m
  else:
    return ''
for line in sys.stdin:
  print regex.sub(repl, line.rstrip('\n'))

본질적으로 우리는 문자열과 문자 리터럴 토큰을 찾은 다음 char 리터럴은 그대로 두고 문자열 리터럴을 제거합니다.char 리터럴 정규식은 문자열 리터럴 정규식과 매우 유사합니다.

루비에서 :

#!/usr/bin/ruby
f=open(ARGV[0],"r")
s=f.read
puts(s.gsub(/"(\\(.|\n)|[^\\"\n])*"/,""))
f.close

표준 출력에 인쇄합니다

pyparsing을 사용하는 파이썬에서 :

from pyparsing import dblQuotedString

source = open(filename).read()
dblQuotedString.setParseAction(lambda : "")
print dblQuotedString.transformString(source)

또한 stdout에 인쇄합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top