파일의 두 줄이 모두 특정 패턴과 일치하는 경우 어떻게 연결합니까?

파일의 두 줄이 모두 특정 패턴과 일치하는 경우 어떻게 연결합니까?

여러 줄이 포함된 파일이 있는데 모두 특정 패턴과 일치하면 연결하고 싶습니다.

다음을 사용하여 패턴에 맞는 줄을 찾고 다음 줄을 얻을 수 있다는 것을 알고 있습니다.

grep -E -A1 'Pattern' filename

하지만 다음 줄도 패턴과 일치하는지 어떻게 확인하고 두 줄을 어떻게 연결합니까?

예를 들어 다음과 같은 파일이 있습니다.

Hello
i
am
John
Smith

예시 패턴은 다음과 같습니다.

'^[A-Z][a-z]+'

따라서 이 경우에는 모두 대문자로 시작하는 줄을 병합하고 싶습니다.

내가 달성하려는 결과는 다음과 같습니다.

Hello
i
am 
John Smith

답변1

/^[A-Z][a-z]+/{
  :a
  N
  /\n[A-Z][a-z]+/{
    s/\n/ /
    b a
  }
}

다른 이름으로 저장 join.sed하고 실행하십시오 sed -Ef join.sed file.

줄이 패턴과 일치하면 패턴 공간에 다음 줄을 추가하고 줄도 패턴과 일치하는 한 줄 바꿈을 공백으로 바꾸는 루프를 시작합니다.

GNU Sed의 경우 한 줄로 축소할 수 있습니다.

sed -E '/^[A-Z][a-z]+/{:a;N;/\n[A-Z][a-z]+/{s/\n/ /;b a}}' file

join.awk또는 패턴이 다음과 같아야 하는 Awk 스크립트 p:

{
    if($0~p)c+=1
    else c=0
    printf "%s%s", (c>1 ? " " : ors), $0
    ors=ORS
}
END{print ""}

구현하다: awk -f join.awk p='^[A-Z][a-z]+' file.

답변2

sednull 문자를 구분 기호( -z) 로 사용합니다 .

$ sed -z 's/\([A-Z][a-z]\+\)\n\([A-Z][a-z]\+\)/\1 \2/'
Hello
i
am
John Smith

답변3

Raku(이전 Perl_6) 사용

raku -e 'given lines.join("\n") { S/ $<first>=[<upper><lower>+] \n $<last>=[<upper><lower>+] /$<first> $<last>/.put};'

입력 예:

Hello
i
am
John
Smith
goodbye

예제 출력:

Hello
i
am
John Smith
goodbye

위 내용은 Perl 계열의 언어인 Raku로 작성된 솔루션입니다. 데이터는 given의 형태로 Raku로 전송되지만 lines, Raku의 lines입력 자동 잘라내기 루틴으로 인해 데이터가 join줄바꿈됩니다. 다소 복잡해 보일 수 있지만 Raku의 lines루틴이 데이터를 느리게 읽을 수 있다는 장점이 있습니다. 즉, 위의 코드는~해야 한다높은 메모리 효율성.

Raku는 친숙한 연산자(Raku에도 있음)와 동일하지는 않더라도 유사한 S///"비파괴적" 연산자를 구현합니다. s///자본 운영자에게는 S이점이 있습니다."원래 문자열을 그대로 유지하고 $/(일치 변수) 대신 결과 문자열을 반환합니다."

연산자의 일치하는(왼쪽) 절반 내에서 S///,명명된 캡처취업하세요. 정규식 엔진은 먼저 이를 검색 [<upper><lower>+]하여 명명된 캡처에 할당한 $<first>다음 하나(개행 문자)를 검색 \n하고 마지막으로 다른 문자를 검색하여 [<upper><lower>+]이번에는 명명된 캡처에 할당합니다 $<last>. 마지막으로 연산자의 대체(오른쪽) 절반에서 S///두 개의 명명된 캡처가 $<first> $<last>왼쪽 일치를 대체하는 데 사용됩니다.그리고공간과아니요\n사이에 줄이 끊어집니다.

동일한 작업을 수행하는 또 다른 방법은 다음과 같습니다. 코드에서는 명명된 캡처를 생략하고 대신 <(\n)>일치 개체에서 캡처 태그 내의 콘텐츠를 제외한 모든 항목을 제거하는 캡처 태그를 사용합니다 <(…)>. 그런 다음 바꾸기에서 공백 \n 으로 바꿉니다.

raku -e 'put S/ [<upper><lower>+] <(\n)> [<upper><lower>+] / / given lines.join("\n");'  

[위 코드는 George\nHerbert\nWalker\nBush4행을 3행으로만 축소합니다( George Herbert\nWalker\nBush). 행에서 연속된 항목을 모두 반환하려면 [<upper><lower>+]이 질문을 게시해 주시기 바랍니다.]

https://docs.raku.org/언어/regexes#S///_non-breaking_substitution
https://docs.raku.org/언어/regexes#index-entry-regex__Named_captures-Named_captures
https://raku.org

관련 정보