헤더별로 청크로 나누어진 데이터 목록이 있습니다. 제목의 시작과 끝 부분에 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 배열 에서 인덱스를 재배열할 때 @
,이는 flat
10개의 결과 순서에 매우 중요 합니다.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
기능을 사용하는 기능입니다. 두 번째 유용한 기능은 raku
Raku의 내부 데이터 표현을 얻기 위해 객체를 호출하는 것입니다. 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"