각 주석 블록의 마지막 주석 줄을 제외하고 모두 삭제

각 주석 블록의 마지막 주석 줄을 제외하고 모두 삭제
  • 표적: 각 주석 블록의 마지막 줄을 제외한 모든 주석 줄을 제거합니다. 파일이 주석 블록으로 끝나면 완전히 삭제하십시오. 각 주석 줄은 으로 시작합니다 #.

  • 내가 시도한 명령

    sed -z -e 's/#.*\n#/#/g' "${InputP}"
    
  • 입력 파일

    # Life/Living
    # Life/Passion
    - [Mindfulness.md](file:///home/nikhil/Documents/Git/Life/Passion/PassionSrc/Sports/Yoga/Mindfulness/Mindfulness.md)
    # Life/PersonalManagement
    # Life/Social
    # Linux/AmazingNotes
    # Linux/Backintime
    # Linux/DotFiles
    # Linux/GitScripts
    - [Peaceful.m3u](file:///home/nikhil/Documents/Git/../Mobile/Documents/PortableNotes/PortableNotesSrc/SocialActivity/Music/SongsPlaylist/Data/Peaceful.m3u)
    - [AuxiliaryFiles.sh](file:///home/nikhil/Documents/Git/Linux/GitScripts/GitScriptsSrc/GitInit/GitNew/Src/AuxiliaryFiles.sh)
    # PythonWs/NumericalProgramming
    # PythonWs/Python
    # PythonWs/ScientificComputing
    
  • 예상 출력

    # Life/Passion
    - [Mindfulness.md](file:///home/nikhil/Documents/Git/Life/Passion/PassionSrc/Sports/Yoga/Mindfulness/Mindfulness.md)
    # Linux/GitScripts
    - [Peaceful.m3u](file:///home/nikhil/Documents/Git/../Mobile/Documents/PortableNotes/PortableNotesSrc/SocialActivity/Music/SongsPlaylist/Data/Peaceful.m3u)
    - [AuxiliaryFiles.sh](file:///home/nikhil/Documents/Git/Linux/GitScripts/GitScriptsSrc/GitInit/GitNew/Src/AuxiliaryFiles.sh)
    
  • 하지만 나는 이 출력을 얻습니다.
    # PythonWs/ScientificComputing
    

이 문제를 해결하는 방법을 아는 사람이 있나요?

답변1

문제는 .*욕심이 많아서 를 sed -z -e 's/#.*\n#/#/g'포함하는 첫 번째 줄부터 #로 시작하는 마지막 줄까지 일치한다는 것입니다 #. 이는 -z패턴 공간의 전체 파일을 한 번에 흡수하는 플래그 때문에 발생합니다(텍스트 파일에 null 바이트가 없다고 가정).

문제를 해결하는 Sed 스크립트는 다음과 같습니다.

sed -n '/^#/N;/\n#/D;p' file
  • /^#/N행이 로 시작하면 #다음 행이 패턴 공간에 추가됩니다.
  • /\n#/D패턴 공간에 newline과 newline이 포함된 경우 #newline 앞의 모든 항목을 삭제하고 새 루프를 시작합니다.
  • p이 명령에 도달하면 패턴 공간이 인쇄됩니다.

유용한 링크

답변2

입력에서 다른 주석 줄이 뒤에 오는 모든 주석 줄을 분명히 제거하려고 합니다. sed기본적으로 정규식이 사용되므로 호출이 실패합니다."탐욕스러운"(즉, 가능한 한 많이 소비), 이는 변경하기 쉽지 않습니다.

awk따라서 명시된 목표에 대한 기반 솔루션을 추가 하겠습니다 .

awk '/^#/{buf=$0;next} {if (buf) {print buf; buf=""}}1' "${InputP}"

또는 약간 더 컴팩트합니다.

awk '/^#/{buf=$0;next} buf{print buf; buf=""}1' "${InputP}"
  • 이렇게 하면 주석 줄이 아닌 모든 줄이 인쇄됩니다( 1규칙 블록 외부는 "지금까지 수정된 모든 내용을 포함하여 현재 줄을 인쇄합니다"를 의미합니다. 이 경우에는 아무 것도 없습니다).
  • 패턴과 일치하는 주석 행이 발견되면 /^#/내용은 버퍼에 저장되지만 buf아직 인쇄되지는 않습니다. 명령 next은 다음 실행 줄로 이동하므로 나머지 코드는 주석 처리되지 않은 줄에만 적용됩니다.
  • 주석이 아닌 줄이 나타나면 버퍼 내용(있는 경우)이 먼저 인쇄되고 실제 줄 내용을 인쇄하기 전에 버퍼가 비워집니다(여러 인쇄를 방지하기 위해).

답변3

GNU sed후루룩 소리 모드를 사용 -z하고 확장 정규식을 활용하면 -E다음을 수행할 수 있습니다.

$ sed -Ez '
    s/(^|\n)(#[^\n]*\n)+$/\1/
    s/(^|\n)(#[^\n]*\n)+/\1\2/g
' file
  • 후행 주석 블록을 제거합니다.
  • 모든 주석 블록을 제거하되 각 주석 블록의 마지막 줄은 유지합니다.

GNU sed 모델은 다음과 같습니다:

  • sed는 파일을 한 줄씩 읽습니다. -z그렇지 않으면 유효하지 않은 경우 전체 파일을 읽습니다. 레코드 구분 기호는 기본적으로 개행으로 설정되며, ASCII를 사용 \n하지 않는 한 NULL 입니다.-z\0
  • 레코드를 읽은 후 후행 레코드 구분 기호가 잘리고 결과 문자열이 패턴 공간 레지스터에 저장됩니다. 패턴 공간은 모든 sed 명령이 실행되는 곳입니다.
  • sed이제 스크립트에 5개의 명령이 있다고 가정해 보겠습니다 sed. 첫 번째 명령은 패턴 공간에 적용되어 패턴 공간을 수정하고, sed다음 명령은 이 수정된 패턴 공간에 적용되며, 마지막 명령까지 계속됩니다. 그런 다음 유효 stdout하지 않은 -n패턴 공간이 인쇄됩니다 . 그 후, 다음 레코드를 읽고 동일한 sed명령 순서가 패턴 공간에 적용됩니다.

위의 내용은 스크립트에서 흐름 제어 명령이 사용되지 않을 때 유효한 매우 단순화된 설명입니다 sed.

예, 맞습니다. 후루룩 소리 모드에서는 $패턴 공간이 하나만 있기 때문에 파일의 끝과 패턴 공간의 끝을 나타냅니다.

이 구문이 있으면 (regex)+정규식의 욕심 ​​많은 특성으로 인해 괄호가 마지막 정규식 일치를 유지합니다.

또는 다음을 수행할 수 있습니다.

$ sed -e '
    /^#/{h;d;} 
    H;z;x;s/^\n//
' file 

답변4

이것은 작동합니다:

perl -ne 'print $x,$_ unless /^#/; $x = /^#/ ? $_ : ""' < infile

게시 한 예상 결과를 얻었습니다.

편집 : 설명

  • 당신이 원한다면 그것을 고려하십시오 $x:-)$left_over_line_to_be_printed
  • 첫 번째 문은 나머지 줄을 모두 인쇄한 다음 현재 줄을 인쇄합니다(현재 줄이 헤더 줄이 아닌 경우).
  • 두 번째 문은 "leftover"를 표시된 마지막 헤더 행 또는 빈 문자열로 설정합니다. (즉, 헤더 행이 아닌 경우 "remaining"은 첫 번째 문에서 이미 인쇄되었기 때문에 빈 문자열이 됩니다. 헤더 행의 경우 해당 행이 됩니다. 여러 헤더 행이 함께 클러스터링되면 결국에는 마지막이 된다).

관련 정보