선택적 그룹은 일치하지 않습니다.

선택적 그룹은 일치하지 않습니다.

다음은 제가 해결하려는 문제의 단순화된 버전입니다. 나는 이 파일을 가지고 있습니다 :

1 H 200 OK.Content-Length: 2422 x
2 H 403 Forbidden.z

나는 HTTP 상태와 - 존재하는 경우 - 컨텐츠 길이와 일치하도록 sed를 얻으려고 시도했습니다.

> sed -nEe 's,^.*H ([ 0-9a-zA-Z]+).*(Content-Length: ([0-9]+))?.*$,\1 \3,p' x
200 OK 
403 Forbidden 

따라서 선택적 그룹은 절대 일치하지 않습니다. 물음표를 제거하여 선택 사항이 아닌 것으로 만들면 내용 길이와 일치하지만 물음표가 없는 줄은 일치하지 않습니다.

> sed -nEe 's,^.*H ([ 0-9a-zA-Z]+).*(Content-Length: ([0-9]+)).*$,\1 \3,p' x
200 OK 2422

다음 출력을 제공하도록 sed를 얻으려면 어떻게 해야 합니까?

200 OK 2422 
403 Forbidden 

주의: 지연 일치( )를 지원하는 Perl도 시도했지만 .*?성공하지 못했습니다.

> perl -pe 's,^.*H ([ 0-9a-zA-Z]+).*?(Content-Length: ([0-9]+))?.*?$,\1 \3,' x
200 OK 
403 Forbidden 

답변1

그룹은 선택 사항 이므로 (Content....)욕심 많은 버전에서는 다음에 대해 다음을 수행합니다.

1 H 200 OK.Content-Length: 2422 x

^.*H ([ 0-9a-zA-Z]+)match 1 H (200 OK), 그런 다음 .*끝까지 일치하고 (Content-Length: ([0-9]+))?다음 .*둘 다 줄 끝의 빈 문자열과 일치합니다.

non-greedy 버전에서는 첫 번째는 .*?가능한 한 적게 일치하려고 시도하지만 나머지 줄( .Content-Length: 2422 x)은 일치하고 (Content-Length: ([0-9]+))?그 이후 .*?$줄 끝까지는 모두 일치하지 않기 때문에 괜찮습니다.

.*첫 번째 캡처 이후 첫 번째 항목이 a 를 스크롤하지 않는지 확인해야 합니다 Content-Length: \d+. 예를 들어 각 단계에서 부정적인 예측을 사용합니다.

perl -lne 'print if
 s/^.*?H ([\s\w]+)(?:(?!Content-Length: \d+).)*(?:Content-Length: (\d+))?.*$/\1\2/'

간단히 이렇게 할 수도 있지만:

perl -lne '
  if (/H\s+([\s\w]+)(.*)/) {
    my $status = $1;
    print "$status" . ($2 =~ /Content-Length: (\d+)/ && " $1");
  }'

또는:

sed -nE 's/^.*H[[:space:]]+([[:space:][:alnum:]]+).*Content-Length: ([[:digit:]]+).*$/\1 \2/p;t
         s/^.*H[[:space:]]+([[:space:][:alnum:]]+).*$/\1/p'

즉, 한 번에 대체하려고 시도하지 마십시오.

답변2

sed에서 정규 표현식은 탐욕적입니다. .*이전에 Content-Length:나머지 문자를 모두 끝까지 일치시켰 습니다 . 상태와 길이 사이에 단 하나의 지점만 있다는 것을 알고 있다면 \.대신 사용하십시오.

sed -r 's/^[0-9]+[ \t]+H[ \t]+([0-9]+[ \t]+[A-Za-z]+)\.(Content-Length:)?([ \t]+[0-9]+)?.*/\1\3/' file

한 줄짜리 명령문도 괜찮지만 sed에는 //if와 유사한 명령문도 있습니다. 아래 스크립트를 사용하여 실행하세요 sed -rf script file.

s/^[0-9]+[ \t]+H[ \t]+([0-9]+[ \t]+[A-Za-z]+)/\1\n/
/\n.*Content-Length:([ \t]+[0-9]+).*/ s//\1\n/
s:\n.*::

sed는 기본적으로 파일에서 한 번에 한 줄만 읽으므로 \n데이터에서 표시할 수 없습니다. 따라서 임시 분리막으로 안전하게 사용할 수 있습니다.

관련 정보