【问题标题】:Dynamically generated regex for gsub not working为 gsub 动态生成的正则表达式不起作用
【发布时间】:2017-07-25 11:59:26
【问题描述】:

我有一个输入 CSV 文件:

1,5,1  
1,6,2  
1,5,3  
1,7,4  
1,5,5  
1,6,6  
1,6,7

我需要创建一个如下的字符串:

;5,1,3,5;6,2,6,7;7,4

所以每个字符,除了第一个是字段$2的值,在;之间的子字符串中的每个字符都表示中间字段的行号;例如;5,1,3,5 表示5 位于行号1,3,5

我一直在尝试将 awk 与 gsub 一起使用,尝试动态创建字符串 MYSTR

gsub 中的正则表达式不起作用。我需要一个匹配;$3$3 的值,可以是两位数)的正则表达式,并将其替换为;$3,RowNO,如果模式不匹配,则在末尾添加;$3字符串。

这是我目前所拥有的:

awk -F',' '{
    print NR, $3;
    noofchars=gsub(/;$3/,";"$3","NR,MYSTR);
    print noofchars;
    if  ( noofchars == 1 )
        ;
    else
        MYSTR=MYSTR";"$3","NR;
    print NR, $3;
    print MYSTR;
}

END{print MYSTR;}' $1

【问题讨论】:

  • 我对您的问题进行了一些编辑。您应该指定“不工作”的含义:会发生什么?你预计会发生什么?

标签: regex awk gsub


【解决方案1】:

正则表达式不起作用,因为 $3 没有被解释为字段 #3 值,而是被视为锚点 $ (匹配行尾) 和文字3

不用gsub也可以:

awk -F, '{a[$2]=a[$2]","NR}END{for (i in a){printf(";%d%s",i,a[i])}}'

【讨论】:

  • 上面的awk代码对我不起作用,完全没看懂。
【解决方案2】:

输入

$ cat file
1,5,1  
1,6,2  
1,5,3  
1,7,4  
1,5,5  
1,6,6  
1,6,7

输出

$ awk -F, '{gsub(/[ ]+/,"",$3);a[$2] = ($2 in a ? a[$2]:$2) FS $3 }END{for(i in a)printf("%s%s",";",a[i]); print ""}' file
;5,1,3,5;6,2,6,7;7,4

可读性更好的版本

awk -F, '
         {
           gsub(/[ ]+/,"",$3);                     # suppress space char in third field          
           a[$2] = ($2 in a ? a[$2]:$2) FS $3      # array a where index being field2 and value will be field3, if index exists before append string with existing value 
         }
      END{             
           for(i in a)                             # loop through array a and print values
                  printf("%s%s",";",a[i]); 
           print ""
         }
        ' file

【讨论】:

    【解决方案3】:

    @vsshekhar:也可以尝试以下操作:它将以正确的顺序为您提供与 Input_file ($2) 相同的值。

    awk -F, '{A[++i]=$2;B[A[i]]=B[A[i]]?B[A[i]] "," FNR:FNR} END{for(j=1;j<=i;j++){if(B[A[j]]){printf(";%s,%s",A[j],B[A[j]]);delete B[A[j]]}};print ""}'  Input_file
    

    现在也添加非单线形式的解决方案。

    awk -F, '{
                    A[++i]=$2;
                    B[A[i]]=B[A[i]]?B[A[i]] "," FNR:FNR
             }
                    END{
                            for(j=1;j<=i;j++){
                                                    if(B[A[j]]){
                                                                    printf(";%s,%s",A[j],B[A[j]]);
                                                                    delete B[A[j]]
                                                               }
                                             };
                            print ""
                       }
            '   Input_file
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多