더 큰 텍스트 블록 세트 내에서 2개의 텍스트 블록을 역방향 정렬

더 큰 텍스트 블록 세트 내에서 2개의 텍스트 블록을 역방향 정렬

헤더별로 청크로 나누어진 데이터 목록이 있습니다. 제목의 시작과 끝 부분에 6개의 "=" 기호가 있습니다. 표시될 수 있는 제목의 수는 제한되어 있지만 매번 모든 제목이 표시되는 것은 아닙니다. 그러나 매번 같은 순서로 나타납니다. 각 블록의 데이터 양은 다양합니다. 이 데이터 세트에서 두 개의 특정 텍스트 블록의 순서를 바꾸고 싶습니다. (설명: 블록 내 데이터의 순서가 아니라 블록이 인쇄되는 순서)

편집: 또 다른 설명: 서로 다른 헤더의 수가 제한되어 있으며 내용을 알고 있지만 파일의 위치는 알 수 없는 두 개의 특정 헤더를 반전시키고 싶습니다. 둘 중 하나만 발생하거나 둘 다 발생하지 않는 경우도 있습니다. 나타나는 경우 항상 동일한 순서로 바로 다음에 나타납니다.

입력 예:

======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======jkl======
data7
======mno======
data8

원하는 출력:

======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

각 헤더 앞에 빈 줄을 추가하고 sed '/======.*======/i\\'다음과 같은 것을 사용 하는 경우이 답변유용할 수도 있지만 Perl을 사용해 본 적이 없고 내가 원하는 대로 수정하는 방법을 모릅니다. 나는 또한 awk가 이것을 할 수 있을 것이라고 생각합니다.

답변1

awk를 사용하십시오.

$ cat tst.awk
/^======[^=]+======$/ {
    key = $0
    gsub(/=/,"",key)
    keys[++numKeys] = key
}
{ key2val[key] = key2val[key] $0 ORS }
END {
    if ( (a in key2val) && (b in key2val) ) {
        tmpVal = key2val[a]
        key2val[a] = key2val[b]
        key2val[b] = tmpVal
    }
    for ( i=1; i<=numKeys; i++ ) {
        key = keys[i]
        printf "%s", key2val[key]
    }
}

$ awk -v a='ghi' -v b='jkl' -f tst.awk file
======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

답변2

이를 위해 awk 및 sed를 사용하는 것이 더 쉬울 수 있습니다. 입력 파일(블록이라고 부르자)에서 시작하여 먼저 jkl 블록을 임시 파일(the_block이라고 함)로 전송합니다.

$ awk '/=jkl=/{p=1; print; next} /======/{p=0}; p>0{print}; p==0{print >"reduced"}' blocks > the_block

두 개의 새 파일을 확인하세요.

$ cat the_block 
======jkl======
data7

$ cat reduced 
======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======mno======
data8

이제 sed를 사용하여 "축소된" 파일에서 예상 블록의 첫 번째 줄 위에 the_block을 삽입하여 최종 결과를 얻습니다.

$ sed '/=ghi=/ {r the_block                                                                           
                  N
                }' reduced 
======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

(이제 임시 파일을 삭제할 수 있습니다)

답변3

그리고GNU 편집기:

printf '%s\n' '/^======ghi======$/kx' '/^======jkl======$/;/^======/-1m'"'x-1" 'w output' | 
  ed -s input

결과:

$ pr -Tm input output 
======abc======                     ======abc======
data1                               data1
data2                               data2
data3                               data3
======def======                     ======def======
data4                               data4
======ghi======                     ======jkl======
data5                               data7
data6                               ======ghi======
======jkl======                     data5
data7                               data6
======mno======                     ======mno======
data8                               data8

답변4

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = slurp.comb( / "======" (<alpha>**3) "======" \v [ \V+ \v]+? <?before "======" | $ > /);  \
            .print for flat @a[0..1,(2..3).sort.reverse,4..*];'  file

또는:

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v ]+? <?before <H> | $ > /);  \
            .print for flat @a[0..1,(2..3).sort.reverse,4..*]'  file

위의 내용은 Perl 프로그래밍 언어 계열인 Raku로 작성된 솔루션입니다. Raku에는 파일 comb에서 찾고 있는 반복 패턴을 선언할 수 있는 기능이 있습니다.split분할기필수 요소 사이). 두 솔루션 모두 slurp전체 파일을 메모리로 읽는 Raku의 기능을 사용합니다 (줄 바꿈 없이).

노트:[ … ]-sigiled 배열 에서 인덱스를 재배열할 때 @,이는 flat10개의 결과 순서에 매우 중요 합니다.Raku(Perl과 달리)는 기본적으로 자동으로 병합되지 않기 때문입니다.

  • 첫 번째 솔루션에서는 먼저 헤더 행을 찾은 "======" (<alpha>**3) "======" \v다음 본문 패턴을 찾습니다 [ \V+ \v ]+?. 이것은 \v내장된 수직 공백 문자 클래스이며 \V내장되어 있습니다.아니요세로 공백 문자 클래스입니다. 이는 ?일치를 탐욕스럽지 않게(즉, 검소하게) 만듭니다. 이는 \V+최소한 하나의 신체 라인이 있어야 함을 의미합니다( \V*허용되는 경우 0 신체 라인으로 변경).

  • 두 번째 솔루션에서는 헤더 줄 패턴이 자체 H정규식 패턴으로 추상화됩니다. 따라서 comb매처에서 다음 호출을 <H>사용하여 /…/헤더 패턴을 검색할 수 있습니다. 이 패턴을 원하는 대로 간단하게 만들거나(예 "======":) 다른 파일에 적용할 수 있습니다. 따라서 이 코드는 상당히 일반적인 솔루션이 될 수 있습니다.

입력 예:

======abc======
data1
data2
data3
======def======
data4
======ghi======
data5
data6
======jkl======
data7
======mno======
data8

예제 출력:

======abc======
data1
data2
data3
======def======
data4
======jkl======
data7
======ghi======
data5
data6
======mno======
data8

Raku에는 몇 가지 유용한 기능이 있으며 그 중 하나는 내장 pairs기능을 사용하는 기능입니다. 두 번째 유용한 기능은 rakuRaku의 내부 데이터 표현을 얻기 위해 객체를 호출하는 것입니다. Raku의 put호출과 결합됨( \n개행 문자로 인쇄됨):

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs;  \
            .raku.put for flat @a[0..1,(2..3).sort.reverse,4..*];'  file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"

#OR (flattening by a different method):

~$ raku -e 'my regex H { "======" <alpha>**3 "======" \v };  \
            my @a = slurp.comb( / <H> [ \V+ \v]+? <?before <H> | $ > /).pairs;  \
            .raku.put for @a[flat(0..1;(2..3).sort.reverse;[email protected])];'  file
0 => "======abc======\ndata1\ndata2\ndata3\n"
1 => "======def======\ndata4\n"
3 => "======jkl======\ndata7\n"
2 => "======ghi======\ndata5\ndata6\n"
4 => "======mno======\ndata8\n"

https://docs.raku.org
https://raku.org

관련 정보