删除每个注释块除了最后一个注释行之外的所有注释

Por*_*ine 4 sed awk text-processing

  • 目标:删除每个注释块除了最后一个注释行之外的所有注释。如果文件以注释块结尾,请将其完全删除。每个注释行都以#.

  • 我试过的命令

    sed -z -e 's/#.*\n#/#/g' "${InputP}"
    
    Run Code Online (Sandbox Code Playgroud)
  • 输入文件

    # 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
    
    Run Code Online (Sandbox Code Playgroud)
  • 预期产出

    # 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)
    
    Run Code Online (Sandbox Code Playgroud)

有谁知道如何解决问题?

Qua*_*odo 9

问题是,.*是贪婪的,因此sed -z -e 's/#.*\n#/#/g'将匹配从包含第一行#达开始的最后一行#。这只是因为-z标志,它一次在模式空间中吞下整个文件(假设文本文件中没有空字节)。

解决您的问题的 Sed 脚本是

sed -n '/^#/N;/\n#/D;p' file
Run Code Online (Sandbox Code Playgroud)
  • /^#/N如果该行以 开头#,则将下一行附加到模式空间。
  • /\n#/D如果模式空间包含一个换行符后跟#,则删除直到换行符为止的所有内容并开始新的循环。
  • p 如果到达此命令,则打印模式空间。

有用的链接


Adm*_*Bee 7

您显然希望从您的输入中删除所有后跟其他注释行的注释行。在sed因为正则表达式是由默认调用失败“贪婪”(即消耗尽可能地),不能轻易改变。

因此,我将为awk既定目标添加一个基于 - 的解决方案:

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

或者,稍微紧凑一点:

awk '/^#/{buf=$0;next} buf{print buf; buf=""}1' "${InputP}"
Run Code Online (Sandbox Code Playgroud)
  • 这将打印所有非注释行不变的行(1规则块的外部意味着“打印当前行,包括迄今为止所做的所有修改” - 在这种情况下没有)。
  • 如果遇到注释行(该行与 patten 匹配/^#/),则内容将存储在缓冲区中buf,但尚未打印。该next命令将执行跳到下一行,因此剩余的代码仅适用于非注释行。
  • 如果遇到非注释行,则在打印实际行内容之前首先打印缓冲区内容(如果有)并清空缓冲区(以防止多次打印输出)。

  • @BANJOSA 是和否。最后,OP 提出了一个目标,并将 `sed` 称为“我尝试过的命令”,因此他们似乎对其他方法持开放态度。 (3认同)
  • @BANJOSA 作为这里的一般规则,我们不仅为提出问题的人而且为未来的访客回答这个问题。使用替代工具给出答案很好,因为 i) OP 可能可以使用其他工具,并且 ii) 下一个遇到相同问题的人可能没有与 OP 相同的偏好。 (3认同)