我有一个输入文件:
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 中将子字符串保存在变量中的方法是使用substr
or 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()
找到正则表达式。
该函数还设置两个特殊变量RSTART
,RLENGTH
它们指示正则表达式的开始和结束位置。