【问题标题】:sed join lines togethersed 将线条连接在一起
【发布时间】:2011-12-12 17:18:01
【问题描述】:

什么是 sed(或其他工具)命令可以将文件中不以字符“0”结尾的行连接在一起?

我会有这样的台词

412|n|Leader Building Material||||||||||d|d|20||0

需要单独放置,然后我会有这样的行,例如(这是 3 行,但只有一个以 w/0 结尾)

107|n|Knot Tying Tools|||||Knot Tying Tools

|||||d|d|0||0

需要合并/合并成一行

107|n|Knot Tying Tools|||||Knot Tying Tools|||||d|d|0||0

【问题讨论】:

    标签: regex linux sed


    【解决方案1】:
     sed ':a;/0$/{N;s/\n//;ba}'
    

    在循环中(分支 ba 到标签 :a),如果当前行以 0 (/0$/) 结尾,则追加下一行 (N) 并删除内部换行符 (s/\n//)。

    awk:

    awk '{while(/0$/) { getline a; $0=$0 a; sub(/\n/,_) }; print}'
    

    Perl:

    perl -pe '$_.=<>,s/\n// while /0$/'
    

    bash:

    while read line; do 
        if [ ${line: -1:1} != "0" ] ; then 
            echo $line
        else echo -n $line
    fi
    done 
    

    【讨论】:

    • 问题说如果行确实NOT 以“0”结尾,则加入。给定 sed 则相反。
    • 这是解决 OP 要求 stackoverflow.com/questions/20094997/… 的问题的解决方案@
    • bash 循环,虽然看起来比较丑陋,但实际上它更快、更灵活、更易于理解和调试。我能够对其进行调整以加入条件为的行:加入以“https”开头的每一行:与以下所有行,直到下一个以“https:”开头的行。
    • 在 macOS 上,分支对我不起作用,但删除它确实有效:sed '/my pattern/{N;s/\n//;}'
    【解决方案2】:

    awk 也可以很短:

    awk '!/0$/{printf $0}/0$/'
    

    测试:

    kent$  cat t
    #aasdfasdf
    #asbbb0
    #asf
    #asdf0
    #xxxxxx
    #bar
    
    kent$  awk '!/0$/{printf $0}/0$/' t
    #aasdfasdf#asbbb0
    #asf#asdf0
    #xxxxxx#bar 
    

    【讨论】:

    • 嗨!你能否添加一个简短的描述这是如何工作的? :)
    • 很直截了当你有什么问题要理解?
    • 好吧:(1) 那是什么命令,有四个斜线? (2) 最后一个“0$”部分是如何工作的? (3)一般来说,如何搜索该命令的文档
    • 已经玩了将近一个小时了,你能确认以下解释吗:对于每行末尾没有 0 的行,打印该行(没有换行符)。然后,另一个正则表达式开始:对于最后 0 的每一行,不要触摸它(这会导致“正常打印它,包括它的换行符”)
    【解决方案3】:

    考虑到 OP 规范:sed join lines together,这个 answer 的评级令人惊讶 ;s(这个令人惊讶的眨眼表情符号双关语 sed 替换是故意的):sed join lines together

    这个submission's最后评论

    “如果是这样,请检查 @ninjalj 提交的内容”

    还建议检查same answer

    即。使用sed ':a;/0$/{N;s/\n//;ba}'逐字检查

    sed ':a;/0$/{N;s/\n//;ba}'
     does
     no one
     ie. 0
     people,
     try
     nothing,
    
     ie. 0
     things,
     any more,
     ie. 0
     tests?
    
              (^D aka eot 004 ctrl-D ␄  ... bash generate via: echo ^V^D)
    

    不会给出(做测试;):

     does no one ie. 0
     people, try nothing, ie. 0
     things, any more, ie. 0
     tests?          (^D aka eot 004 ctrl-D ␄  ... bash generate via: echo ^V^D)
    

    要得到这个用途:

    sed 'H;${z;x;s/\n//g;p;};/0$/!d;z;x;s/\n//g;'
    

    或:

    sed ':a;/0$/!{N;s/\n//;ba}'
    

    不是:

    sed ':a;/0$/{N;s/\n//;ba}'
    

    注意事项:

    sed 'H;${x;s/\n//g;p;};/0$/!d;z;x;s/\n//g;'
    

    不使用分支和
    等同于:

    sed '${H;z;x;s/\n//g;p;};/0$/!{H;d;};/0$/{H;z;x;s/\n//g;}'
    
    • H 开始所有序列
    • d 使当前行上的进一步脚本命令执行短路并开始下一个循环,因此/0$/! 之后的地址选择器只能是/0$/!!,因此
      /0$/{H;z;x;s/\n//g;} 的地址选择器是多余的,不需要。李>
    • 如果一行不以 0 结尾,则将其保存在保留空间中
      /0$/!{H;d;}
    • 如果一行确实以 0 结尾,也保存它,然后打印冲洗(双关,即清除并对齐行)
      /0$/{H;z;x;s/\n//g;}
    • 注意${H;z;x;s/\n//g;p;} 使用/0$/ ... 命令和一个额外的p 来强制最终打印和现在不需要的z(用于清空和重置像s/.*// 这样的模式空间)

    【讨论】:

      【解决方案4】:

      一个典型的神秘 Perl 单行代码:

      perl -pe 'BEGIN{$/="0\n"}s/\n//g;$_.=$/'
      

      这使用序列“0\n”作为记录分隔符(根据您的问题,我假设每一行都应该以零结尾)。任何记录都不应有内部换行符,因此将其删除,然后打印该行,附加已删除的 0 和换行符。

      另一个问题是确保每行有 17 个管道分隔字段。这并不假定第 17 个字段值必须为零。

      awk -F \| '
          NF == 17 {print; next}
          prev {print prev $0; prev = ""}
          {prev = $0}
      '
      

      【讨论】:

        【解决方案5】:

        如果以 0 结尾,则删除换行符..

        sed '/0$/!N;s/\n//'
        

        【讨论】:

        • 我不认为这很有效。如果我理解这个问题,那么完全没有零应该给出一条大线。但是当我尝试`$ ls | sed '/0$/!N;s/\n//' 我发现它只能成对加入行。
        • 埃里克,你是对的。如果没有 0 那么我需要删除换行符
        • 如果是这种情况,请检查@ninjalj 提交的内容。
        猜你喜欢
        • 2011-08-09
        • 1970-01-01
        • 2020-04-08
        • 2023-03-15
        • 2017-02-08
        • 1970-01-01
        • 2015-01-03
        • 1970-01-01
        • 2020-03-22
        相关资源
        最近更新 更多