【问题标题】:bash find and replace "enter" with comma before given patternbash 在给定模式之前查找并用逗号替换“输入”
【发布时间】:2016-12-09 06:42:09
【问题描述】:

我有一个大的 CSV 文件,其中包含如下段落:

first line1  
second line1  
third line1  
fourth line1  
first line2  
second line2  
third line2  
fourth line2

处理后我想翻译成这样:

first line1,second line1,third line1,fourth line1  
first line2,second line2,third line2,fourth line2

注意:第一行、第二行等包含特殊字符,如 . , " :

我在想一个选项可能是从第二行 1 中找到“第二个”单词并将其前面的“输入”替换为逗号,这样第二行 1 将位于第一行 1 的右侧。

我该怎么做?

确实,上面的例子很可能不是真实的ACTUAL数据,这里是:

137822118,user,User,192.168.100.20,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ABCD_BD,Succeeded,"NE Name:B12345-BXL_ABCD_BD  
MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.20"";  
MML Result:Successful.  
",2016-07-25 23:19:05 DST  
137821234,user,User,192.168.100.21,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ASDF_BD,Succeeded,"NE Name:B12345-BXL_ASDF_BD  
MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.21"";  
MML Result:Successful.  
",2016-07-25 22:18:05 DST

CSV 文件包含大量此类段落。

输出应该是(一行一行):

137822118,user,User,192.168.100.20,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ABCD_BD,Succeeded,"NE Name:B12345-BXL_ABCD_BD,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.20""; MML Result:Successful.  ",2016-07-25 23:19:05 DST    
137821234,user,User,192.168.100.21,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ASDF_BD,Succeeded,"NE Name:B12345-BXL_ASDF_BD,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.21""; MML Result:Successful.  ",2016-07-25 22:18:05 DST

非常感谢您的帮助!

我尝试了您的解决方案,它几乎可以工作,但不是预期的结果。 由于这里的发布格式,我给您的示例似乎与源文件略有不同。

请在下面找到真正的源CSV文件(只有几行,因为完整的文件包含超过一百万)

https://www.wetransfer.com/downloads/637b36b2148550ad090c22c9e8297a9c20160804081835/48b90b

抱歉造成误会,再次感谢!

【问题讨论】:

  • 一组总是有 4 行吗?请显示实际数据,以便我们查看特殊字符的位置等。
  • 这是stackoverflow.com/q/38731863/1745001 的副本,但我无法将其作为副本关闭,因为那里的答案尚未被投票或接受。

标签: linux bash awk sed tr


【解决方案1】:

试试这个;

 awk -v patt="first" 'BEGIN{ORS=","}$0 ~ patt {gsub(patt, "\n"patt)}1'  CSVfile

【讨论】:

  • 它留下逗号。
【解决方案2】:

您可以为此使用paste,例如:

$ paste -d, - - - - < file
first line1,second line1,third line1,fourth line1
first line2,second line2,third line2,fourth line2

- 表示标准输入,当您指定其中 N 个时(本例中 N=4), paste 将从标准输入的 N 行组成一行。

-d是指定列分隔符,在本例中为逗号。

【讨论】:

    【解决方案3】:
    $ awk 'NR==1 {prev=$0; next} {printf "%s", prev; printf "%s", $0~/^[0-9]{9}/ ?"\n":","; prev=$0} END{print prev}' test.in
    137822118,user,User,192.168.100.20,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ABCD_BD,Succeeded,"NE Name:B12345-BXL_ABCD_BD  ,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.20"";  ,MML Result:Successful.  ,",2016-07-25 23:19:05 DST
    137821234,user,User,192.168.100.21,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ASDF_BD,Succeeded,"NE Name:B12345-BXL_ASDF_BD  ,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.21"";  ,MML Result:Successful.  ,",2016-07-25 22:18:05 DST
    

    当一条新记录以一堆数字开头时,就该换行了。下次请把正确的数据一开始就贴出来。

    【讨论】:

      【解决方案4】:

      另一种选择

      $ awk '{ORS=NR%4?",":RS}1' file
      

      每四行重置输出记录分隔符并打印。

      【讨论】:

        【解决方案5】:

        将 GNU awk 用于 FPAT,并且不假设您的输入有多少行或字段,或者记录的开头/结尾出现了哪些字段值:

        $ cat decsv.awk
        BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")"; OFS="," }
        {
            # create strings that cannot exist in the input to map escaped quotes to
            gsub(/a/,"aA")
            gsub(/\\"/,"aB")
            gsub(/""/,"aC")
        
            # prepend previous incomplete record segment if any
            $0 = prev $0
            numq = gsub(/"/,"&")
            if ( numq % 2 ) {
                # this is inside double quotes so incomplete record
                prev = $0 OFS
                #prev = $0 RT   # uncomment to retain newlines in the record
                next
            }
            prev = ""
        
            for (i=1;i<=NF;i++) {
                # map the replacement strings back to their original values
                gsub(/aC/,"\"\"",$i)
                gsub(/aB/,"\\\"",$i)
                gsub(/aA/,"a",$i)
            }
        
            print
        
            #printf "Record %d:\n", ++recNr
            #for (i=0;i<=NF;i++) {
                #printf "\t$%d=<%s>\n", i, $i
            #}
            #print "#######"
        }
        

        .

        $ awk -f decsv.awk file
        137822118,user,User,192.168.100.20,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ABCD_BD,Succeeded,"NE Name:B12345-BXL_ABCD_BD  ,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.20"";  ,MML Result:Successful.  ,",2016-07-25 23:19:05 DST
        137821234,user,User,192.168.100.21,2016-07-25 23:19:05 DST,iScript,iScript send MML command,B12345-BXL_ASDF_BD,Succeeded,"NE Name:B12345-BXL_ASDF_BD  ,MML Command:LST DEVIP:OPONEMS=""user"", IPOFEMSWS=""192.168.100.21"";  ,MML Result:Successful.  ,",2016-07-25 22:18:05 DST
        

        请参阅Awk to get .csv column containing commas and newlines 了解更多信息。

        【讨论】:

          猜你喜欢
          • 2020-02-28
          • 1970-01-01
          • 1970-01-01
          • 2021-07-28
          • 1970-01-01
          • 2018-05-14
          • 1970-01-01
          • 2014-02-21
          • 2023-03-23
          相关资源
          最近更新 更多