【问题标题】:Filter text which appears between two marks过滤出现在两个标记之间的文本
【发布时间】:2011-06-09 23:19:56
【问题描述】:

第 1 部分

创建仅输出由两个预定义标记包围的文本的文本过滤器的最简单方法是什么。我不介意使用任何标准工具:sed、awk、python、...

例如,我希望只显示由“Mark Begin”和“Mark End”包围的文本。

input:
Text 1
Mark Begin
Text 2
Mark End
Text 3
Mark Begin
Text 4
MarK End
Text 4

output:
Text 2
Text 4

第 2 部分

如何修改解决方案,以便仅将最后一次出现写入输出,因此对于上面相同的输入,我们得到:

output:
Text 4

【问题讨论】:

    标签: python shell text awk filtering


    【解决方案1】:
    $ awk '/Mark End/{f=0}/Mark Begin/{f=1;next}f' file
    Text 2
    Text 4
    
    $ awk '/Mark End/{f=0}/Mark Begin/{f=1;next}f{p=$0}END{print p}' file
    Text 4
    

    【讨论】:

    • 感谢所有回答的人。我选择了这个,因为它对我来说最简单:最容易从命令行使用。
    【解决方案2】:

    第 1 部分

    awk '
        tolower($0) ~ /mark begin/ {printing = 1; next}
        tolower($0) ~ /mark end/   {printing = 0; next}
        printing                   {print}
    '
    

    第 2 部分

    awk '
        tolower($0) ~ /mark begin/ {capturing = 1; text = ""; next}
        tolower($0) ~ /mark end/   {capturing = 0; sep = ""; next}
        capturing                  {text = text sep $0; sep = "\n"}
        END                        {print text}
    '
    

    【讨论】:

      【解决方案3】:

      我找到了一个很好的解决方案:

      awk '/Mark End/, /Mark Begin/' file.lst
      

      第二种情况,但毕竟需要标记过滤。

      【讨论】:

        【解决方案4】:

        使用 Python 和惰性生成器的功能性(无状态)实现:

        import itertools
        
        def get_lines_between_marks(ilines, start_mark, end_mark):
            for line in ilines:
                if line.strip().lower() == start_mark:
                    yield list(itertools.takewhile(lambda s: s.strip().lower() != end_mark, ilines))
        
        for group in get_lines_between_marks(open("file.txt"), "mark begin", "mark end"):
            for line in group:
                print line,
        # Text 2
        # Text 4
        

        现在您的第二个请求是微不足道的(请参阅 iterlast here):

        def iterlast(it):
            return reduce(lambda x, y: y, it)
        
        for line in iterlast(get_lines_between_marks(open("file.txt"), "mark begin", "mark end")): 
            print line,
        # Text 4
        

        【讨论】:

          【解决方案5】:

          分别输出:

          sed -n '/^Mark Begin$/{:a;n;/^Mark End$/b;p;ba}' inputfile
          

          输出最后一个

          sed -n '${x;s/\n//;p};/^Mark Begin$/{x;s/.*//;x;:a;n;/^Mark End$/b;H;ba}'
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-13
            • 2015-06-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多