일치하는 패턴 간의 행을 열로 변환하는 Bash 스크립트

일치하는 패턴 간의 행을 열로 변환하는 Bash 스크립트

내 입력 파일은 다음과 같습니다.

START
line1
line2
line3
END
START
line11
line22
line33
END

내 스크립트가 다음과 같이 출력되기를 원합니다.

START line1 line2 line3 END
START line11 line22 line33 END

도와주세요.

답변1

사용 awk:

$ awk '{printf "%s", $0 (($0 == "END") ? ORS : OFS)}'

START에서 까지 줄을 서려면 END다음을 사용할 수 있습니다.

$ awk '($0 =]"START"),($0 == "END"){printf "%s%s",$0, ($0=="END" ? ORS : OFS)}'

그렇지 않은 경우 다음 명령을 사용할 수 있습니다 START.END

$ awk '($0 == "START"){a="";} {a = a $0 (($0 == "END") ? "" : OFS)}  ($0 == "END"){print a}'

답변2

다중 문자에는 GNU awk를 사용 RS하고 RT다음 예와 같이 데이터에 항상 완전하고 중첩되지 않으며 겹치지 않는 START-END 블록이 있다고 가정합니다.

$ awk -v RS='\nEND\n' -F'\n' '{$0=$0 RT; $1=$1} 1' file
START line1 line2 line3 END
START line11 line22 line33 END

START-END 블록 외부에 행을 추가할 수 있는 경우 대신 다음을 수행하십시오.

$ awk -v RS='\nEND\n' -F'\n' 'RT{$0=gensub(/.*\n(START\n)/,"\\1",1) RT; $1=$1; print}' file
START line1 line2 line3 END
START line11 line22 line33 END

또는 awk를 사용하십시오.

$ awk '
    $0 == "START" { f=1; rec=$0; next }
    f { rec=rec OFS $0; if ( $0 == "END" ) { print rec; f=0 } }
' file
START line1 line2 line3 END
START line11 line22 line33 END

중첩되거나 겹치거나 불완전한 START-END 블록이 있고 위에서 원하는 대로 작동하지 않는 경우 이러한 요구 사항을 표시하도록 질문을 편집해야 합니다.

답변3

사용 sed:

$ sed -n -e '/^START$/ { h; d; }' -e H -e '/^END$/ { g; y/\n/ /; p; }' file
START line1 line2 line3 END
START line11 line22 line33 END

스크립트 sed는 주석과 함께 보기 좋게 인쇄됩니다.

# Save each "START" line in the hold space and skip to the next line.
/^START$/ {
    h
    d
}

# Append all non-"START" lines to the hold space.
H

# On an "END" line, get the hold space, convert newlines to spaces, and print.
/^END$/ {
    g
    y/\n/ /
    p
}

이는 "START" 및 "END" 행의 범위가 겹치지 않고 "END"와 "START" 사이에 추가 데이터가 없다고 가정합니다.

답변4

사용행복하다(이전 Perl_6)

END한 레코드와 다음 레코드 사이(예: 및 사이 ) 의 중간 행을 삭제하려면 START:

~$ raku -ne 'S/ <!after END> $/ / andthen do if /^START/ fff s/^END$/END\n/ {.print};'  file

또는:

~$ raku -ne 'S/ <!after END> $/ / andthen print ($_ if /^START/ fff s/^END$/END\n/) ;'  file

위의 내용은 Raku 프로그래밍 언어로 코딩된 답변입니다. 즉, -ne명령줄 플래그는 자동 인쇄 없이 입력 파일에서 코드를 한 줄씩 실행하는 데 사용됩니다. 단어로 끝나지 않는 각 줄에 대해 S///"big-S" 대체 연산자를 사용하고 (부정적 뒤돌아보기) 공백을 추가합니다. 이 단계를 사용하면 사이에 공백이 있는 줄을 쉽게 연결할 수 있습니다(참고: @Kusalananda가 댓글에 게시한 것과 유사한 답변을 얻는 데 사용됨).<!after END> $END\t

계속해서 $_테마 변수 다시 로드를 사용하세요 andthen. 이제 Raku의 sed와 유사한 /START/ fff /STOP/"트리플 f" 트리거 연산자를 사용하여 원하는 센티넬 라인 사이의 라인을 캡처할 수 있습니다. 형식 지정 트릭에서 실제로 동일한 트리거 연산자 의 센티넬 라인을 s/^END$/END\n/대체하고 그 뒤에 줄바꿈을 추가 할 수 있습니다 .ENDfff\nEND

마지막으로 출력은 print자체 개행 문자를 추가하지 않고 위의 공백/개행 형식을 유지하는 Raku의 간단한 연산자를 통해 수행됩니다.

입력 예:

START
line1
line2
line3
END
test
START
line11
line22
line33
END

출력 예(가운데 줄 제거):

START line1 line2 line3 END
START line11 line22 line33 END

자, 어떻게 하면 중간선을 지킬 수 있을까요? 간단합니다. fffRaku의 "whatever-star"를 사용하여 모든 출발선을 허용 하도록 트리거 연산자를 변경하기만 하면 됩니다 . *아래를 참조하세요:

~$ raku -ne 'S/ <!after END> $/ / andthen do if * fff s/^END$/END\n/ {.print};'  file
START line1 line2 line3 END
test START line11 line22 line33 END

#OR

~$ raku -ne 'S/ <!after END> $/ / andthen print ($_ if * fff s/^END$/END\n/);'  file
START line1 line2 line3 END
test START line11 line22 line33 END

https://docs.raku.org/syntax/S%2F%2F%2F%20Non-destructive%20replacement
https://docs.raku.org/routine/fff
https://docs.raku.org/routine/andthen
https://raku.org

관련 정보