두 줄이 모두 패턴에 맞는 경우 파일의 두 줄을 어떻게 결합할 수 있나요?

두 줄이 모두 패턴에 맞는 경우 파일의 두 줄을 어떻게 결합할 수 있나요?

여러 줄이 포함된 파일이 있고 둘 다 특정 패턴에 맞는 경우 줄을 결합하고 싶습니다.

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

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에 전달되지만 linesRaku의 lines일상적인 자동 씹기 입력에 따라 데이터는 join줄 바꿈으로 -ed됩니다. 다소 복잡해 보일 수 있지만 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\nBush[참고로 위의 코드는 4줄에서 3줄( ) 로만 축소됩니다 George Herbert\nWalker\nBush. 한 줄에 모든 줄 단위로 연속적으로 반환되도록 하려면 [<upper><lower>+]해당 질문을 자유롭게 게시하십시오.]

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

관련 정보