【问题标题】:Column manipulating using Bash & Awk使用 Bash 和 Awk 进行列操作
【发布时间】:2020-04-08 06:23:22
【问题描述】:

假设有一个由几行组成的 example1.txt 文件。

item item item  
 A    B    C      
100  20   2       
100  22   3
100  23   4
101  26   2
102  28   2
103  29   3
103  30   2
103  32   2
104  33   2
104  34   2
104  35   2
104  36   3

我想执行几个命令来过滤掉 txt 文件并添加更多列。

首先,我想在 C 项等于 2 时应用条件。使用 awk 命令我可以通过以下方式做到这一点。

因此返回的文本文件是:

awk '$3 == 2 { print $1 "\t"  $2  "\t" $3} ' example1.txt > example2.txt

item item item
 A    B    C      
100  20   2       
101  26   2
102  28   2
103  30   2
103  32   2
104  33   2
104  34   2
104  35   2

现在我要数两件事:

我想计算第 1 列中的总唯一数。

For example, in the above case example2.txt, it would be:
(100,101,102,103,104) = 5

我想添加重复列 A 编号并将其添加到新列中。

我想要这样的:

item item item  item
 A    B    C     D
100  20   2      1
101  26   2      1
102  28   2      1
103  30   2      2
103  32   2      2
104  33   2      3
104  34   2      3
104  35   2      3

~

Item D 列(第 4 列)上方,第 1 行是 1,因为它没有任何重复。但在第 4 行,它是 2,因为 103 重复了两次。因此,我在第 4 列和第 5 列中添加了 2。同样,第 4 项中的最后三列是 3,因为在这三列中,项 A 重复了 3 次。

【问题讨论】:

    标签: awk


    【解决方案1】:

    你可以试试这个awk:

    awk -v OFS='\t' 'NR <= 2 {
       print $0, (NR == 1 ? "item" : "D")
    }
    FNR == NR && $3 == 2 {
       ++freq[$1]
       next
    }
    $3 == 2 {
       print $0, freq[$1]
    }' file{,}
    

    item  item  item  item
    A     B     C     D
    100   20    2     1
    101   26    2     1
    102   28    2     1
    103   30    2     2
    103   32    2     2
    104   33    2     3
    104   34    2     3
    104   35    2     3
    

    【讨论】:

      【解决方案2】:

      请您尝试以下操作。如果您想将输出保存到相同的 Input_file 中,请将 &gt; temp &amp;&amp; mv temp Input_file 附加到以下代码中。

      awk '
      FNR==NR{
        if($3==2){
          a[$1,$3]++
        }
        next
      }
      FNR==1{
        $(NF+1)="item"
        print
        next
      }
      FNR==2{
        $(NF+1)="D"
        print
        next
      }
      $3!=2{
        next
      }
      FNR>2{
        $(NF+1)=a[$1,$3]
      }
      1
      ' Input_file  Input_file | column -t
      

      输出如下。

      item  item  item  item
      A     B     C     D
      100   20    2     1
      101   26    2     1
      102   28    2     1
      103   30    2     2
      103   32    2     2
      104   33    2     3
      104   34    2     3
      104   35    2     3
      


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

      awk '                    ##Starting awk program fro here.
      FNR==NR{                 ##Checking condition if FNR==NR which will  be TRUE when 1st time Input_file is being read.
        if($3==2){             ##Checking condition if 3rd field is 2 then do following.
          a[$1,$3]++           ##Creating an array a whose index is $1,$3 and keep adding its index with 1 here.
        }
        next                   ##next will skip further statements from here.
      }
      FNR==1{                  ##Checking condition if this is first line.
        $(NF+1)="item"         ##Adding a new field with string item in it.
        print                  ##Printing 1st line here.
        next                   ##next will skip further statements from here.
      }
      FNR==2{                  ##Checking condition if this is second line.
        $(NF+1)="D"            ##Adding a new field with string item in it.
        print                  ##Printing 1st line here.
        next                   ##next will skip further statements from here.
      }
      $3!=2{                   ##Checking condition if 3rd field is NOT equal to 2 then do following.
        next                   ##next will skip further statements from here.
      }
      FNR>2{                   ##Checking condition if line is greater than 2 then do following.
        $(NF+1)=a[$1,$3]       ##Creating new field with value of array a with index of $1,$3 here.
      }
      1                        ##1 will print edited/non-edited lines here.
      ' Input_file Input_file   ##Mentioning Input_file names 2 times here.
      

      【讨论】:

      • 如果您想将输出保存到同一个 Input_file 中,然后将 > temp && mv temp Input_file 附加到上述代码中。
      【解决方案3】:

      与其他类似,但使用 awk 单次传递并将信息存储在数组中有关记录 seenD 的计数与数组 ordDcnt 用于映射每个人的信息,例如

      awk '
          FNR == 1 { h1=$0"\titem" }      # header 1 with extra "\titem"
          FNR == 2 { h2=$0"\tD" }         # header 2 with exter "\tD"
          FNR > 2 && $3 == 2 {            # remaining rows with $3 == 2
              D[$1]++                     # for D colum times A seen
              seen[$1,$2] = $0            # save records seen
              ord[++n] = $1 SUBSEP $2     # save order all records appear
              Dcnt[n] = $1                # save order mapped to $1 for D
          }
      END {
          printf "%s\n%s\n", h1, h2       # output headers
          for (i=1; i<=n; i++)            # loop outputing info with D column added
              print seen[ord[i]]"\t"D[Dcnt[i]]
          }
      ' example.txt
      

      (注意: SUBSEP 是一个内置变量,对应于使用逗号连接数组索引字段时使用的子字符串分隔符,例如 seen[$1,$2] 允许在外部进行比较一个数组。默认是"\034")

      示例输出

      item item item  item
      A    B    C    D
      100  20   2     1
      101  26   2     1
      102  28   2     1
      103  30   2     2
      103  32   2     2
      104  33   2     3
      104  34   2     3
      104  35   2     3
      

      使用awk给猫剥皮的方法总是不止一种。

      【讨论】:

        【解决方案4】:

        假设文件不是大文件;

        awk 'NR==FNR && $3 == 2{a[$1]++;next}$3==2{$4=a[$1];print;}' file.txt file.txt
        

        您对文件进行了两次解析。在第一次迭代中,您计算​​第 4 列并将其放入数组中。在第二次解析中,我们将计数设置为第 4 列,并打印整行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-27
          • 1970-01-01
          相关资源
          最近更新 更多