중첩으로 빈 블록 제거

중첩으로 빈 블록 제거

양식의 빈 구성 블록을 제거하고 싶습니다(중첩 가능).

입력 파일:

abc {
a
}
bcd {
    spq {
    }
}
ecd pqr {
}
xyz {
so
}

예상 출력:

abc {
a
}
xyz {
so
}

나는 시도했다:

sed '/{$/{N;/{\n\s}$/d}' SampleToDelete.txt

그러나 이것은 도움이 되지 않습니다. 새로운 줄과 공백을 표현할 수 없습니다.

답변1

$ sed -n -f script.sed file
abc {
a
}
xyz {
so
}

script.sed어디

1 {
    # 1st line, save it to the hold space
    # and skip to next line.
    h
    d
}

# Append all other lines to hold space
# with an embedded newline as delimiter.
H

$ {
    # Last line, swap in hold space
    # (which by now contains the whole document).
    x

    # Replace all empty "word { ... }" sections
    # until there are no more such sections.
    # "word" may be a single word or multiple words
    # separated by whitespace.

    :again
    s/[[:alnum:][:space:]]*[[:space:]]*{[[:space:]]*}//g
    t again

    # Squeeze multiple newlines into single newlines.
    s/\(\n\)\1*/\1/g

    # Output.
    p
}

[[:space:]]패턴은 공백 및 개행(및 기타 공백과 유사한 문자)과 일치합니다.

패턴은 비어 있거나 공백 문자(공백, 탭, 줄 바꿈 등)만 포함된 [[:alnum:][:space:]]*[[:space:]]*{[[:space:]]*}섹션 중 하나와 일치하며 단일 단어이거나 공백으로 구분된 여러 단어일 수 있습니다. 또한 "익명" 빈 부분과도 일치합니다(예 : 선행 태그 없음).word { ... }{ ... }word{ }word

루프에서 빈 부분이 제거됩니다( again코드의 레이블). t가장 최근 s명령이 하나 이상의 대체를 수행한 경우 명령은 지정된 레이블로 분기됩니다. 그렇다면 제거할 빈 섹션이 더 많아져서 루프가 생성될 수 있습니다.

다음과 같은 데이터의 경우

a { b { c { d { e { } } } } }

루프는 s명령을 5번 실행합니다(결국 모든 것을 삭제함).


귀하의 sed스크립트:

/{$/{N;/{\n\s}$/d}

또는 긴 형식으로,

/{$/ {
    N
    /{\n\s}$/d
}

빈 섹션을 포함하는 섹션은 에서처럼 제거할 수 없습니다 a { b { } }. 또한 섹션 레이블과 섹션의 모양 가능성을 무시하는 것 같습니다 a { b { } abc c { d { } } }(변환되지 않고 두 줄로 분할된 경우 완전히 제거됩니다 a { abc }). .

또한 무엇이 일치하는지 잘 모르겠지만 GNU 와 일치하는 \s것 같습니다 . 표준에서는 줄 바꿈이나 명령 끝 부분에 필요하므로 스크립트는 끝 부분에 있어야 합니다(한 줄 버전의 경우).[[:space:]]sedsed;d;}

관련 정보