在awk中定义变量

在awk中定义变量

我有一个输入文件:

3.59717487E+05  3.40210880E+06        4075.32   7066.00   4075.32 7066      4075.322 2 a_final_psdm_LY1-1250_20160307             
3.59725248E+05  3.40211860E+06        4063.53   7067.00   4063.53 7067      4063.527 2 a_final_psdm_LY1-1250_20160307             
3.59733009E+05  3.40212840E+06        4051.73   7068.00   4051.73 7068      4051.731 2 a_final_psdm_LY1-1250_20160307             
3.59740771E+05  3.40213820E+06        4039.94   7069.00   4039.94 7069      4039.936 2 a_final_psdm_LY1-1250_20160307   

我需要获取最后一列并定义一个变量,即 LY1-1250 部分。这是我到目前为止所拥有的:

awk ' 
BEGIN{

     if($NF !~ /LY1/){
       print
     }
     else{

        tag=$NF
        print tag
     }
 }

但这给了我 tag=a_final_psdm_LY1-1250_20160307

我需要标签=LY1-1250

在 shell 脚本中我会这样做

标签=`回声 $NF | sed ...等等等等

但在 awk 中,它似乎没有计算表达式。

答案1

由于“标签”是倒数第二个之后的部分_,因此您可以简单地将其用作字段分隔符:

$ awk -F_ '{if($(NF-1)~/LY1/){print $(NF-1)}else{print}}' file
LY1-1250
LY1-1250
LY1-1250
LY1-1250

或者,将其用作变量:

awk -F_ '{if($(NF-1)~/LY1/){tag=$(NF-1); print tag}else{print}}' file

我不明白为什么你的代码在一个BEGIN{}块中,它只会在读取任何行之前运行一次,所以NF甚至不会被定义。

无论如何,对于一般情况,在 awk 中将子字符串保存在变量中的方法是使用substror sub。所以,你也可以这样做:

$ awk '{ 
        if($NF~/LY1/){
            tag=$NF; 
            sub(/.*LY1/,"LY1",tag); 
            sub(/_[^_]*$/,"",tag); 
            print tag
        }
        else{ print } }' file
LY1-1250
LY1-1250
LY1-1250
LY1-1250

答案2

我认为您可能误解了 的条件awk。每行的开头条件。这是一种更... awk-ward 的方式来做到这一点:怎么样

awk '
/LY1/ { 
        tag=gensub(/_.*/,"","1",gensub(/.*LY1/,"LY1","1", $NF))
        print tag
        next
}
{
    print
}' input.file

第一个/LY1/是隐式matches条件 - 仅当输入行与正则表达式匹配时才执行表达式。该表达式首先将该行上的所有内容替换为 ,直到(包括),LY1并将LY1其放入变量标记中。然后它打印标签,并且next- 语句跳过所有其他表达式为了这个记录

之后是一个无条件表达式,它只是按原样打印该行 - 但如果执行了先前的表达式,则不会执行该表达式,因为这会调用next.

答案3

尝试一下这个:

awk '
{
   if(!match($NF,"LY1[^_]*")){
     print
   }
   else {
     tag=substr($NF,RSTART,RLENGTH)
     print tag
   }
}' input.file

match()找到正则表达式。

该函数还设置两个特殊变量RSTARTRLENGTH它们指示正则表达式的开始和结束位置。

相关内容