【问题标题】:awk to extract days from lineawk 从行中提取天数
【发布时间】:2021-03-22 09:19:36
【问题描述】:

我有以下 csv 文件

238013750030646-2;;"Default";"2020-10-01 00:40:36";;"opening";0;3591911;283940640
238013750030646-2;;"Default";"2020-10-03 00:40:36";;"closing line";0;89320;283940640
238013750030646-2;;"something-else";"2020-10-04 00:40:36";;"started";0;0;283940640
238013750030646-2;;"default else";"2020-10-08 05:42:06";;"opening";0;2410;283940640

我试图将每一行存储在与每一行的日期匹配的特定文件中,日期在每行的第 4 列,所以第一行 ("2020-10-01 00:40:36") 应该在 output-01.csv 中,第二行在output-03.csv

这个 awk 命令

awk -F";|-" -vOFS='\t' '{print > "output-"$7".csv"}' testing.csv

由于第 3 列中的 -,一半工作但在第 3 行失败,由于第 3 列中的 ,第 4 行失败 - 这会产生 output-10.csv

有没有办法两次运行 awk 命令?然后我可以使用; 分隔符提取日期,然后使用- 进行拆分

【问题讨论】:

  • 能否请您在238013750030646-2;;"Default";"2020-10-01 00:40:36";;"opening";0;3591911;283940640 线上解释一下您要提取的确切数字?抱歉,不清楚您是说应该是output-01,所以如果您能简单地突出显示您想要的字段,那就太好了,谢谢。
  • @RavinderSingh13 我已经更新了问题,抱歉
  • @tripleee 我确实看到了那个问题,但是我需要存储整行,并且无法使用该问题的建议答案来解决问题
  • 有几个类似的重复项。如果您有包含结构化信息的字段,我的建议是在顶层使用单个分隔符,然后在辅助分隔符上使用 split

标签: awk


【解决方案1】:

使用 gawk 也可以处理 未排序的 文件:

awk 'match($0,/([0-9]{4})-([0-9]{2})-([0-9]{2})/,arr){
          file=sprintf("output-%s.csv",arr[3]);
          if(!seen[file]++){
              print >file; 
              next         
          }     
     }{
        print >>file; 
        close(file);
     }' infile

说明:

awk 'match($0,/([0-9]{4})-([0-9]{2})-([0-9]{2})/,arr){   # match for regex
          file=sprintf("output-%s.csv",arr[3]);          # file variable using array arr value, 3rd index
          if(!seen[file]++){                             # if not seen file name before in array seen
              print >file;                               # print content to file
              next                                       # go to next line          
          }     
     }{
        print >>file;                                    # append content to file 
        close(file);                                     # close file
     }' infile

【讨论】:

    【解决方案2】:

    试试这个:

    $ awk -F';' -v OFS='\t' '{split($4,a,/[- ]/); file = "output-"a[3]".csv";
                              $1=$1; print > file; close(file)}' testing.csv
    
    • split($4,a,/[- ]/) 这将根据空格或- 字符进一步拆分第四个字段,保存在数组a
    • file = "output-"a[3]".csv" 输出文件名
    • $1=$1 因为没有其他命令改变输入行的内容,所以需要重建输入行,否则不会应用OFS
    • print > file 将输入行打印到所需文件
    • close(file)调用close,文件名过多时很有用

    如果第 4 列与示例中所示一致,您也可以使用 file = "output-" substr($4,10,2) ".csv" 代替 split

    【讨论】:

    • 感谢您的解释,真正有助于理解您的答案
    • 如果/当多个输入行出现相同的日期时,这将失败,因为它会在每次出现时覆盖该日期的输出文件。如果我们首先按时间戳字段对输入进行排序,也可以更有效地完成。
    【解决方案3】:

    使用您展示的示例,请尝试使用 GNU awk 进行跟踪、编写和测试。

    awk '
    match($0,/[0-9]{4}(-[0-9]{2}){2}/){
      outputFile=substr($0,RSTART+8,RLENGTH-8)".csv"
      print >> (outputFile)
      close(outputFile)
    }
    ' Input_file
    

    说明:为上述添加详细说明。

    awk '                                 ##Starting awk program from here.
    match($0,/[0-9]{4}(-[0-9]{2}){2}/){   ##using match function to match yyyy-mm-dd here in line.
      outputFile=substr($0,RSTART+8,RLENGTH-8)".csv" ##Getting matched regex sub-string into outputFile here.
      print >> (outputFile)               ##Printing current line into outputFile here.
      close(outputFile)                   ##Closing output file to avoid too many files opened error.
    }
    ' Input_file                          ##Mentioning Input_file name here.
    

    【讨论】:

      【解决方案4】:

      要有效地做到这一点,您应该首先对关键字段进行排序:

      awk -F';' '{print $4, NR, $0}' file |
      sort -k1,1 -k3,3n |
      awk '
          { curr=$1; sub(/([^ ]+ ){2}/,"") }
          curr != prev { close(out); out="output-" (++c) ".csv"; prev=curr }
          { print > out }
      '
      

      $ head output*.csv
      ==> output-1.csv <==
      238013750030646-2;;"Default";"2020-10-01 00:40:36";;"opening";0;3591911;283940640
      
      ==> output-2.csv <==
      238013750030646-2;;"Default";"2020-10-03 00:40:36";;"closing line";0;89320;283940640
      
      ==> output-3.csv <==
      238013750030646-2;;"something-else";"2020-10-04 00:40:36";;"started";0;0;283940640
      
      ==> output-4.csv <==
      238013750030646-2;;"default else";"2020-10-08 05:42:06";;"opening";0;2410;283940640
      

      以上内容可以在每个 Unix 机器上的任何 shell 中使用任何 awk+sort 来工作。请参阅此站点上的许多类似示例以获取说明。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        • 2013-08-15
        • 2013-05-09
        相关资源
        最近更新 更多