다음과 같은 파일이 있습니다.
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
등. 블록 내의 행을 뒤집어야 하지만 다른 모든 항목은 다음과 같이 순서대로 유지되어야 합니다.
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
sed나 awk를 사용하여 이를 수행하는 방법은 무엇입니까? 블록을 거꾸로 뒤집었지만 다시 제자리에 놓을 수는 없습니다.
sed -n '/block = {.$/,/}$/p' inputfile | tac
답변1
Perl을 사용해도 괜찮다면:
perl -ne 'if($f && /}/){$f=0; print @blk};
$f ? unshift(@blk, $_) : print;
if(/block = {/){$f=1; @blk=()}' ip.txt
if(/block = {/){$f=1; @blk=()}
배열을 초기화하고 입력 행에 다음이 포함된 경우@blk
플래그를 설정합니다.$f
block = {
$f ? unshift(@blk, $_) : print
이 플래그가 활성화되어 있으면 배열 앞에 입력 줄을 삽입하고@blk
, 그렇지 않으면 입력 줄을 인쇄합니다.if($f && /}/){$f=0; print @blk}
플래그가 활성화되어 있고 입력 행에 다음이 포함되어 있으면 플래그를 설정 해제하고 배열}
의 내용을 인쇄합니다.@blk
그리고 awk
:
awk 'f && /}/{f=0; for(i=c; i>=1; i--) print blk[i]}
{if(f) blk[++c] = $0; else print}
/block = {/{f=1; c=0}' ip.txt
답변2
들여쓰기를 사용하여 해당 끝을 perl
찾는 또 다른 접근 방식은 다음과 같습니다 .}
block = {
perl -C -0777 -pe '
s{^(\h*)block = \{\n\K.*?\n(?=\1\}$)}{
join "", reverse $& =~ m{.*\n}g
}gems' < your-file
답변3
sed
코드를 작성하기는 쉽지만 읽기는 어렵다는 것을 증명해 보세요 :
sed '/block = {/,/}/{/[{}]/!{G;h;d;};x;s/.$//p;g;s/.*//;x;}' file
예약된 공간에 현재 예약된 공간을 추가하여 반전할 라인(중괄호가 없는 라인)을 모으는 것입니다(그래서 순서가 자동으로 변경됩니다). 코드는 이식 가능하며 sed
어떤 구현에서도 사용할 수 있습니다. 상세히:
/block = {/,/}/
block = {
}
직접 선택하는 것처럼 에서 다음까지의 각 범위를 선택하세요 . 다른 모든 유사한 코드는xyz
변경되지 않고 인쇄됩니다./[{}]/!{G;h;d;}
중괄호 없이 행 처리(블록 행):G
현재 예약된 공간을 추가하고h
결과를 예약된 공간으로 이동한 후d
출력과 함께 해당 행 처리를 중지합니다.- 나머지는 지원 라인에 대해서만 실행됩니다. 여기에서
x
버퍼를 변경하여 예약된 공간에 있는 줄을 인쇄한 다음,s/.$//p
예약된 빈 공간에 추가하여 도입된 예약된 공간에서 후행 줄 바꿈을 제거해야 합니다. ubstitude 명령p
에 대한 옵션은s
빈 예약 공간이 인쇄되는 것을 방지하기 위해 성공적인 대체에만 인쇄됩니다. 마지막으로g
예약된 공간에서 현재 행을 복원하는 데 사용됩니다. - 마지막으로 보유 공간을 비워야 합니다:
s/.*//;x
:현재 라인을h
이전 공간에 저장하고, 패턴 공간을 비우고 버퍼를 교체하여 보유 공간은 비워지고 패턴 공간에는 출력을 위해 현재 라인이 다시 포함됩니다.
답변4
사용행복하다(이전 Perl_6)
~$ raku -ne 'BEGIN my @blk; if (/block/ && .put) { for lines() {
if /\}/ { put join "\n", (@blk.pop xx @blk.elems, $_); last};
@blk.push: $_ }
} else { .put };' file
#OR (more simply)
~$ raku -ne 'BEGIN my @blk; if (/block/ & .put) { for lines() {
if /\}/ { .put for (@blk.pop xx @blk.elems, $_).flat; last};
@blk.push: $_ }
};' file
위 코드는 Perl 계열 언어인 Raku로 작성되었습니다. -ne
비자동 인쇄 플래그를 사용하여 입력을 한 줄씩 읽습니다. BEGIN
블록 내에서 @blk
배열이 선언되고 if
"블록" 문자열(키워드)이 발견되며 lines
마지막 }
닫는 중괄호가 읽혀집니다. 읽어서 배열 로 lines
편집 하고 Curlie 끝이 발견되면 완전히(즉, 역순으로) 닫힙니다.push
@blk
pop
}
last
입력 예:
x = {
y = {
z = {
block = {
line1
line2
line3
}
}
}
}
x2 = {
y2 = {
block = {
line4
line5
}
}
}
xyz
block = {
line6
}
예제 출력:
x = {
y = {
z = {
block = {
line3
line2
line1
}
}
}
}
x2 = {
y2 = {
block = {
line5
line4
}
}
}
xyz
block = {
line6
}
부록: @Sundeep의 뛰어난 Perl5 솔루션에 대한 Raku 번역을 찾는 사람은 다음을 참조하세요.
~$ raku -ne 'BEGIN my @blk; state $f;
if ($f && /\}/) {$f=0; .put for @blk};
$f ?? unshift(@blk, $_) !! .put;
if (/block/) {$f=1; @blk=()};' file