【问题标题】:Shell script to remove a word between "." and "," in the first line of a fileShell脚本删除“。”之间的单词。和“,”在文件的第一行
【发布时间】:2015-09-05 13:53:59
【问题描述】:

我有一个 CSV 文件,其中包含以下格式的第一行。

aaa.bbb.ccc.ddd,eee.fff.ggg.hhh,iii.jjj.kkk.lll,mmm.nnn.ooo.ppp
  • 需要读取 CSV 文件的第一行。
  • 然后,读取第三个., 之间的单词,即输出应如下所示。 ddd,hhh,lll,ppp
  • 将上述输出替换为 CSV 文件中的第一行。

我想在 shell 脚本上完成这项工作。

谢谢

基兰库马尔 G

【问题讨论】:

    标签: shell csv


    【解决方案1】:

    你可以使用这个 awk 命令:

    awk -F '[.,]' 'NR==1{s=$4; for(i=8; i<=NF; i+=4) s=s "," $i; print s}' file
    ddd,hhh,lll,ppp
    

    -F '[.,]' 将输入字段分隔符设为,.

    NR==1 将使其仅针对第一条记录运行。

    【讨论】:

    • 感谢 Anubhava 的解决方案,它对我来说很好,因为我需要在 shell 脚本中使用它。需要更多信息,如果源字符串不是常规模式,比如 aa.bb、cc.dd、ee.ff、gg.hh.ii.jj、kk.ll.mm.nn - 那么如何获取单词的之前 ”,” ?输出应该是——bb、dd、ff、jj、nn。请求您的帮助。谢谢。
    【解决方案2】:
    # Maintain current IFS
    OIFS=$IFS
    
    # Read each CSV value into array
    IFS=',' read -a array < path_to_file.csv    
    replacementString=""
    
    # Iterate through each item
    for element in "${array[@]}"; do
    
        # Concatenate each last value of period separated values
        replacementString="$replacementString,$(echo $element | cut -d "." -f 4)"
    
    done
    
    # Replace first line with new string, minus leading comma
    sed -i -e "1s/.*/${replacementString#?}/" path_to_file.csv  
    
    # Restore original IFS
    IFS=$OIFS
    

    【讨论】:

      【解决方案3】:

      您可以考虑使用 Perl:
      更改脚本中的文件名并运行:

      $ ./<script name>.pl > newfile.csv
      
      #!/usrbin/perl -w
      
      $thefile = "yourfile.csv";
      open(CSV_FILE, $thefile) or
         die "\nError: cannot open file $thefile\n\n";
      
      while ($line = <CSV_FILE>)
      {
         if ($. == 1)
         {
             chomp($line);
             @comma_chunks = split(/,/,$line);
             foreach my $commachunk (@comma_chunks)
             {
                 @dot_chunks = split(/\./,$commachunk);
                 push(@last_dot_chunks, $dot_chunks[-1]); # last of the dotchunks 
             }
             $new_first_line = join(',', @last_dot_chunks);
             print "$new_first_line\n";
         }
         else
         {
             print $line;
         }
      }
      

      【讨论】:

        【解决方案4】:
        #!/usr/bin/env perl
        
        use Tie::File;
        tie my @a, 'Tie::File', $ARGV[0] or die "$ARGV[0]:$!";
        $a[0] =  join ",",  map { (split /\./)[3] } split ',', $a[0];
        

        使用您的文件名作为第一个参数调用该脚本。如果您坚持使用 shell 脚本执行此操作,那么这样做可能是最简单的:

        #!/bin/sh
        
        perl -e '
        use Tie::File;
        tie my @a, "Tie::File", $ARGV[0] or die "$ARGV[0]:$!";
        $a[0] =  join ",",  map { (split /\./)[3] } split ",", $a[0];
        ' input-file
        

        尽管您可能应该将 input-file 替换为 $1 并将文件名作为第一个参数传递。 Tie::File 是一个不错的小模块,它将绑定的文件映射到一个数组,因此您可以简单地操作数组的元素并在文件中进行更改。在这种情况下,我们只是将您的输入文件绑定到数组@a,然后按照您的描述拆分第一个字段。

        【讨论】: