【问题标题】:I want to remove multiple line of text on linux我想在 linux 上删除多行文本
【发布时间】:2021-05-31 09:31:21
【问题描述】:

就像这样。
之前:

1
19:22
abcde

2
19:23

3
19:24
abbff

4
19:25
abbc

之后:

1
19:22
abcde

3
19:24
abbff

4
19:25
abbc

我想删除没有字母的部分,如第 2 部分。
我认为我应该使用 perl 或 sed。但我不知道该怎么做。 我试过这样。但它没有用。

sed 's/[0-9]\n[0-9]\n%s\n//'

【问题讨论】:

    标签: linux perl awk sed


    【解决方案1】:

    sed 用于在单独的行上执行 s/old/new/,仅此而已。对于其他任何你应该使用 awk 的东西:

    $ awk -v RS= -v ORS='\n\n' '/[[:alpha:]]/' file
    1
    19:22
    abcde
    
    3
    19:24
    abbff
    
    4
    19:25
    abbc
    

    上面就是这样:

    • RS= 告诉 awk 输入记录用空行分隔。
    • ORS='\n\n' 告诉 awk 输出记录也必须用空行分隔。
    • /[[:alpha:]]/ 搜索并打印包含字母字符的记录。

    【讨论】:

      【解决方案2】:

      在 Perl 中足够简单。秘诀是通过将输入记录分隔符 ($/) 设置为空字符串来将 Perl 置于“段落模式”。然后我们只打印包含字母的记录。

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      # Paragraph mode
      local $/ = '';
      
      # Read from STDIN a record (i.e. paragraph) at a time
      while (<>) {
        # Only print records that include a letter
        print if /[a-z]/i;
      }
      

      这是作为 Unix 过滤器编写的,即它从 STDIN 读取并写入 STDOUT。所以如果它在一个名为filter的文件中,你可以这样调用它:

      $ filter < your_input_file > your_output_file
      

      或者,这是一个简单的 Perl 命令行脚本(-00 是将 Perl 置于段落模式的命令行选项):

      $ perl -00 -ne'print if /[a-z]/' < your_input_file > your_output_file
      

      【讨论】:

        【解决方案3】:

        如果每个段落之后正好有一个空行,您可以使用长的awk oneliner(三种模式,所以实际上可能不是 oneliner):

        $ echo '1
        19:22
        abcde
        
        2
        19:23
        
        3
        19:24
        abbff
        
        4
        19:25
        abbc
        ' |  awk '/[^[:space:]]/ { accum = accum $0 "\n" } /^[[:space:]]*$/ { if(on) print accum $0; on = 0; accum = "" } /[[:alpha:]]/ { on =  1 }'
        1
        19:22
        abcde
        
        3
        19:24
        abbff
        
        4
        19:25
        abbc
        

        这个想法是累积非空行,一旦找到字母字符就设置标志,并在空白输入行上,如果设置了该标志,则刷新整个累积的段落,将 accum 重置为空字符串并将 flag 重置为零。

        (请注意,如果输入的最后一行不一定为空,您可能需要添加一个END 块来检查当前是否有未刷新的段落并根据需要刷新它。)

        【讨论】:

          【解决方案4】:

          这可能对你有用(GNU sed):

          sed ':a;$!{N;/^$/M!ba};/[[:alpha:]]/!d' file
          

          收集由空行或文件结尾分隔的行,如果最新的集合不包含字母字符,则删除它。

          这假定文件格式是固定的,如示例中所示。为了更准确地使用:

          sed -r ':a;$!{N;/^$/M!ba};/^[1-9][0-9]*\n[0-9]{2}:[0-9]{2}\n[[:alpha:]]+\n?$/!d' file
          

          【讨论】:

            【解决方案5】:

            类似于Ed Morton的解决方案,但有以下假设:

            • 文本块由 2 或 3 行组成。
            • 如果有第三行,则它包含任何字母表中的字符。

            本质上,在这些条件下,我们只需要检查第三个字段:

            awk 'BEGIN{RS=;ORS="\n\n";FS="\n"}(NF<3)' file
            

            或类似的没有BEGIN:

            awk -v RS= -v ORS='\n\n' -F '\n' '(NF<3)' file
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-11
              • 2020-06-07
              • 1970-01-01
              相关资源
              最近更新 更多