【问题标题】:Merge two rows in UNIX using Sed / Awk在 UNIX 中使用 Sed/Awk 合并两行
【发布时间】:2015-07-11 11:46:53
【问题描述】:

考虑在 UNIX 中具有以下管道分隔行的源文件。此示例有五行。第 1,2 和 4 行很好,但第 3 行和第 5 行由于文本中的换行符而分成两行。我必须将第 3 行合并为单行,将第 5 行合并为单行,方法是仅在 t 处删除新行,然后加载到 oracle 表中。

如何使用 sed / awk 或任何其他 UNIX 命令来实现?

输入示例:

 1. 9187-001|COS 60W 16G T1A CLV|||||10  
 2. 9184-002|COS 48W 28G NT SKO|FOOTAGE/SEQUENCE GRIDS||||10  
 3. 9679-229|COS 56G 40G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES  
(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10  
 4. 9184-230|COS48W 48G NT LIF SKO|LIFE STORE COSMETIC FOOTAGE/SEQUENCE GRID||||10  
 5. 9679-230|COS 56G 44G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES  
(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10 

期望的输出:

1. 9187-001|COS 60W 16G T1A CLV|||||10  
2. 9184-002|COS 48W 28G NT SKO|FOOTAGE/SEQUENCE GRIDS||||10  
3. 9679-229|COS 56G 40G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10  
4. 9184-230|COS48W 48G NT LIF SKO|LIFE STORE COSMETIC FOOTAGE/SEQUENCE GRID||||10  
5. 9679-230|COS 56G 44G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10

【问题讨论】:

    标签: regex bash unix awk sed


    【解决方案1】:

    通过 perl,

    perl -00pe 's/\n(?!\h*\d)//g' file
    

    $ perl -00pe 's/\n(?=\()//g' file
     1. 9187-001|COS 60W 16G T1A CLV|||||10  
     2. 9184-002|COS 48W 28G NT SKO|FOOTAGE/SEQUENCE GRIDS||||10  
     3. 9679-229|COS 56G 40G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10  
     4. 9184-230|COS48W 48G NT LIF SKO|LIFE STORE COSMETIC FOOTAGE/SEQUENCE GRID||||10  
     5. 9679-230|COS 56G 44G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10 
    

    【讨论】:

      【解决方案2】:

      也可以在awk中完成

      awk '{if(!match($0,"[0-9]\\. ")){print prev$0}else{print $0}; prev=$0}' file
      

      【讨论】:

      • 你不需要 match 只是为了测试一个匹配,你只需要它之后你想使用 RSTART/RLENGTH。 match() 的第二个参数是正则表达式而不是字符串,因此请使用正则表达式分隔符,然后您就不需要双重转义 match($0,/[0-9]\. /)。您不需要将 $0 指定为 print 的 arg,因为这是默认设置。你的整个命令可以简化为awk '{print (/[0-9]\. /?"":prev) $0; prev=$0}' file(但它仍然不会产生所需的输出)。
      • 是的,你是对的。它给出了重复的行,所以我会用awk '{if(!match($0,"[0-9]\\. ")){printf $0}else{printf "\n"$0}; prev=$0};END{printf "\n"}' 之类的东西替换它,但我必须承认 Glenn Jackmans 的解决方案更简单、更优雅。至于您的评论,我喜欢指定默认​​参数,因为它似乎使代码更清晰,但感谢match() 中有关正则表达式分隔符的信息。
      • 永远不要使用printf $0,而是始终使用printf "%s", $0。想象一下如果$0 包含%s 或其他一些printf 格式字符串会有什么不同。这应该非常符合您指定所有参数的理念,无论它们是否需要。您也不需要那些虚假的分号。
      • 感谢有用的 cmets。
      【解决方案3】:

      看来每一行应该有7个字段:

      awk -F'|' '
          {$0 = prev $0} 
          NF < 7 {prev = $0} 
          NF == 7 {print; prev=""}
      ' file
      

      但实际上,您应该使用正确的 CSV 解析器:

      perl -MText::CSV -Mautodie -E '
          $csv = Text::CSV->new({binary => 1, sep_char => "|", quote_space => 0});
          open $fh, "<", shift;
          while ($row = $csv->getline($fh)) {
              $csv->combine( map {s/\n//g; $_} @$row );
              say $csv->string();
          }
      ' file
      
       1. 9187-001|COS 60W 16G T1A CLV|||||10  
       2. 9184-002|COS 48W 28G NT SKO|FOOTAGE/SEQUENCE GRIDS||||10  
       3. 9679-229|COS 56G 40G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES  (ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10  
       4. 9184-230|COS48W 48G NT LIF SKO|LIFE STORE COSMETIC FOOTAGE/SEQUENCE GRID||||10  
       5. 9679-230|COS 56G 44G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES  (ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10 
      

      【讨论】:

        【解决方案4】:

        使用 GNU awk 进行多字符 RS:

        $ awk -v RS='^$' -v ORS= '{gsub(/\s*\n\(/,"(")}1' file
         1. 9187-001|COS 60W 16G T1A CLV|||||10
         2. 9184-002|COS 48W 28G NT SKO|FOOTAGE/SEQUENCE GRIDS||||10
         3. 9679-229|COS 56G 40G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10
         4. 9184-230|COS48W 48G NT LIF SKO|LIFE STORE COSMETIC FOOTAGE/SEQUENCE GRID||||10
         5. 9679-230|COS 56G 44G NT SVO|"FOOTAGE/SEQUENCE GRIDS FOR STREETSCAPE STORES(ALL COSMETICS ON 60"" HIGH GONDOLAS"||||10
        

        【讨论】:

          猜你喜欢
          • 2020-09-22
          • 1970-01-01
          • 2015-02-21
          • 2011-04-07
          • 2015-02-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多