이 질문은 다음에서 비롯됩니다. 여러 줄 텍스트 파일에서 중괄호 사이의 모든 텍스트를 삭제하는 방법은 무엇입니까?(동일하지만 중첩 요구 사항은 없습니다).
예:
This is {
{the multiline
text} file }
that wants
{ to {be
changed}
} anyway.
다음과 같아야 합니다:
This is
that wants
anyway.
이를 수행하는 데 사용할 수 있는 일종의 한 줄 bash 명령(awk, sed, perl, grep, cut, tr...등)이 있습니까?
답변1
$ sed ':again;$!N;$!b again; :b; s/{[^{}]*}//g; t b' file3
This is
that wants
anyway.
설명하다:
:again;$!N;$!b again
전체 파일을 읽습니다.
:again
라벨입니다.N
다음 줄을 읽고,$!N
마지막 줄에 도달하지 않은 경우 다음 줄을 읽습니다. 마지막 줄이 아닌 경우 레이블$!b again
로 다시 분기합니다 .again
:b
이는 label 을 정의합니다
b
.s/{[^{}]*}//g
이렇게 하면 텍스트에 내부 중괄호가 포함되어 있지 않은 한 중괄호 안의 텍스트가 제거됩니다.
t b
위의 대체 명령으로 인해 변경이 발생하면 label 로 다시 이동하세요
b
. 이런 방식으로 모든 가새 그룹이 제거될 때까지 바꾸기 명령을 반복합니다.
답변2
펄 방법:
$ perl -F"" -a00ne 'for (@F){$i++ if /{/; $i||print; $i-- if /}/}' file
This is
that wants
anyway
설명하다
-a
-F
: 배열에 지정된 파일 구분 기호에 대한 자동 분할을 켭니다@F
.-F""
@F
: 입력 필드 구분 기호를 공백으로 설정합니다. 그러면 각 요소가 입력 문자 중 하나 가 됩니다 .-00
: "줄"이 두 개의 연속 줄 바꿈으로 정의되는 단락 모드를 켭니다. 이는 이 경우 전체 파일이 한 줄로 처리된다는 것을 의미합니다. 파일에 여러 단락이 있을 수 있고 대괄호가 여러 단락에 걸쳐 있을 수 있는 경우 대신 를 사용하세요-0777
.-ne
: 입력 파일을 읽고 주어진 스크립트를-e
각 줄에 적용합니다.
스크립트 자체는 실제로 매우 간단합니다. 카운터는 a가 보일 때마다 1씩 증가하고 {
, 보일 때마다 1씩 감소합니다 }
. 이는 카운터가 0일 때 대괄호 안에 있지 않으며 다음을 인쇄해야 함을 의미합니다.
for (@F){}
:@F
줄의 모든 요소, 모든 문자에 대해 이 작업을 수행합니다.$i++ if /{/;
:$i
캐릭터가 1개라면 1개 추가{
$i||print;
:$i
설정되지 않은 경우 인쇄합니다(0은 설정되지 않은 것으로 간주).$i-- if /}/
:$i
문자가 1이면 1씩 감소}