【问题标题】:awk - pull out pair columns and get the count of occurrencesawk - 拉出对列并获取出现次数
【发布时间】:2021-05-21 10:46:28
【问题描述】:

我有一个表模式 - 以逗号分隔的列名。为了清楚起见,我将它们放在每行一列中,如下所示

$ cat cols_name.txt
id
resp
x_amt
rate1
rate2
rate3
pay1
pay2
rate_r1
rate_r2
x_rate1
x_rate2
x_rate3
x_rate_r1
x_rate_r2
x_pay1
x_pay2
rev1
x_rev1

我需要找出与列对 ( pay1 -> x_pay1 ) 匹配的对,并将它们列在一起作为中间输出,如下所示

x_rate1 rate1
x_rate2 rate2
x_rate3 rate3
x_pay1 pay1
x_pay2 pay2
x_rate_r1 rate_r1
x_rate_r2 rate_r2
x_rev1 rev1

然后最后将频率打印为

 pay 2
 rate 3
 rate_r 2
 rev 1

在我尝试获取中间输出时,下面的 awk 命令不起作用。

awk ' NR==FNR { if( $1~/^x_/ ) a[$1]=1 ; next }  $1~/"x_" a[$1]/ { print $0 } ' cols_name.txt cols_name.txt

它没有打印任何东西。可以帮忙解决一下吗

【问题讨论】:

  • 您能否修改 cols_name.txt 的帖子,以展示当您 cat 时它的实际外观?
  • 真的需要打印该中间输出还是只是认为您需要这样做才能获得最终输出?
  • @EdMorton.. 是的.. 我也需要中间输出..
  • @EdMorton.. 中间输出将用于下游处理.. 其中 x_ 名称将重命名为其对.. 即删除非“x_”相应列.. 频率部分用于记录目的。
  • 那么您是否希望将频率值输出到 stderr 或其他文件,这样它就不会与 stdout 中的对混在一起?

标签: linux awk


【解决方案1】:

这里是单程 awk 来完成它:

 awk '/^x_/ {xk[$0]; next} {s=$0; sub(/[0-9]+$/, "", s); xv[$0]=s} END {for (i in xv) if ("x_" i in xk) {print "x_" i, i; ++fq[xv[i]]}; print "== Summary =="; for (i in fq) print i, fq[i]}' file

x_rev1 rev1
x_rate1 rate1
x_rate2 rate2
x_rate3 rate3
x_rate_r1 rate_r1
x_pay1 pay1
x_rate_r2 rate_r2
x_pay2 pay2
== Summary ==
rate_r 2
rate 3
rev 1
pay 2

更易读的形式:

awk '
/^x_/ {
   xk[$0]
   next
}
{
   s = $0
   sub(/[0-9]+$/, "", s)
   xv[$0] = s
}
END {
   for (i in xv)
      if ("x_" i in xk) {
         print "x_" i, i
         ++fq[xv[i]]
      }
   print "== Summary =="
   for (i in fq)
      print i, fq[i]
}' file

【讨论】:

    【解决方案2】:

    在每个 Unix 机器上的任何 shell 中使用任何 awk,并假设输入文件中的每个条目只出现一次,如您发布的示例所示:

    $ cat tst.awk
    {
        sub(/^x_/,"")
        pair = "x_" $0 OFS $0
        if ( ++count[pair] == 2 ) {
            print pair
            sub(/[0-9]+$/,"")
            freq[$0]++
        }
    }
    END {
        print "---"
        for (key in freq) {
            print key, freq[key]
        }
    }
    

    $ awk -f tst.awk cols_name.txt
    x_rate1 rate1
    x_rate2 rate2
    x_rate3 rate3
    x_rate_r1 rate_r1
    x_rate_r2 rate_r2
    x_pay1 pay1
    x_pay2 pay2
    x_rev1 rev1
    ---
    rate_r 2
    rev 1
    rate 3
    pay 2
    

    【讨论】:

      【解决方案3】:

      假设文件实际上是:

      id,resp,x_amt,rate1,rate2,rate3,pay1,pay2,rate_r1,rate_r2,x_rate1,x_rate2,x_rate3,x_rate_r1,x_rate_r2,x_pay1,x_pay2,rev1,x_rev1
      

      按照原帖中的建议(不是很清楚),使用 GNU awk:

      awk '{ split($0,map,",");for (i in map) { map1[map[i]]="1" } for (i in map) { if ( map[i] ~ /^x_/ ) { hd=gensub("x_","","g",map[i]);hd1=gensub("[[:digit:]]","","g",hd);if (map1[hd]=="1") { map2[hd1]++;print map[i]" "hd } } } printf "\n";for (i in map2) { print i" "map2[i] } }' cols_name.txt
      

      解释:

      awk '{ 
              split($0,map,",");                                     # Split the line into an array called map, using comma as the separator
              for (i in map) { 
                 map1[map[i]]="1"                                    # Loop through map and create another array map1 with the values of map as indexes
              } 
              for (i in map) { 
                 if ( map[i] ~ /^x_/ ) {                            
                     hd=gensub("x_","","g",map[i]);                  # Loop through map and it the value is prefixed with "x_", remove it, reading the result into hd
                     hd1=gensub("[[:digit:]]","","g",hd);            # Take any digits out of hd and read into hd1
                     if (map1[hd]=="1") {
                       map2[hd1]++;                                  # Create a third array map2 with the index hd1 and the value an incrementing counter 
                       print map[i]" "hd                             # If a match exists in the map1 array, print the match
                     } 
                  } 
               } 
               printf "\n";
               for (i in map2) { 
                  print i" "map2[i]                                  # Loop through the count array and print the values
               }   
             }' cols_name.txt
      

      输出:

      x_pay2 pay2
      x_rev1 rev1
      x_rate1 rate1
      x_rate2 rate2
      x_rate3 rate3
      x_rate_r1 rate_r1
      x_rate_r2 rate_r2
      x_pay1 pay1
      
      rate_r 2
      rate 3
      rev 1
      pay 2
      

      【讨论】:

      • amt 没有对应的,它不应该在输出中
      • 抱歉,map2的创建需要在if语句中进行。立即尝试。
      【解决方案4】:

      对于您展示的示例,您能否尝试在 GNU awk 中使用展示的示例进行跟踪、编写和测试。

      awk -v s1="x_" '
      FNR==NR{
        if($0~"^"s1){
          arr[$0]=$0
        }
        next
      }
      ((s1 $0) in arr){
        print arr[s1 $0],$0
        gsub(/^x_|[0-9]+$/,"",$0)
        sum[$0]++
      }
      END{
        for(i in sum){
          print i,sum[i]
        }
      }
      '  Input_file  Input_file
      

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

      awk -v s1="x_" '             ##Starting awk program from here.
      FNR==NR{                     ##Checking condition which will be TRUE when first time Input_file is being read.
        if($0~"^"s1){              ##Checking condition if line starts with s1 value then do following.
          arr[$0]=$0               ##Creating arr with current line index and value with current line.
        }
        next                       ##next will skip all further statements from here.
      }
      ((s1 $0) in arr){            ##Checking condition if s1 $0 is present in arr then do following.
        print arr[s1 $0],$0        ##Printing value of array with current line.
        gsub(/^x_|[0-9]+$/,"",$0)  ##Globally substituting starting x_ AND ending digits with NULL in current line.
        sum[$0]++                  ##Creating sum with inceasing value of 1 each time cursor comes here.
      }
      END{                         ##Starting END block of this question from here.
        for(i in sum){             ##Traversing through sum elements here.
          print i,sum[i]           ##Printing key and value of sum in here.
        }
      }
      '  Input_file  Input_file    ##Mentioning Input_file names here.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-08
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 2017-05-01
        • 1970-01-01
        相关资源
        最近更新 更多