2017-02-27 34 views
1

字段的值可能的标题是不是一个很好的说明,但本质上,这是我试图解决的问题:AWK:更换模式匹配字段与以前行

  • 我有一个文本文件与ñ行和空间分体字段在每一行中
  • 如果字段Ĵ行的一个模式匹配,与现场Ĵ行替换它我 - 1

我不是被迫使用AWK(GAWK在这个例子中),但它似乎是这个操作的一个不错的选择。这是我写的,并预期它的工作sript,但我想知道是否有解决问题

{ 
    if ($0!~/NoData/) { 
     split($0, data, " "); 
     print $0 
    } else { 
     split($0, row, " ", seps); 
     for(i in row) {if (row[i]~/NoData/) row[i]=data[i]; else data[i]=row[i]; printf "%s%s", row[i], seps[i];} 
     printf "\n"                                    
    } 
} 

为样本,该脚本更加节省时间的方式,在此输入文件运行

0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 NoData 0.0357 0.3922 0.0462 
0.6324 0.1576 NoData NoData 0.6555 0.0971 
0.0975 0.9706 NoData NoData 0.1712 0.8235 

应该产生这样的结果

0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 0.8003 0.0357 0.3922 0.0462 
0.6324 0.1576 0.8003 0.0357 0.6555 0.0971 
0.0975 0.9706 0.8003 0.0357 0.1712 0.8235 

回答

2
awk '{for(i=1;i<=NF;i++){ if($i~/NoData/){ $i=last[i]; } last[i]=$i } }1' file 

如果你想保留原来的格式,你可以使用是低,如果你有gawksplit的第四个参数可能被利用。

awk '{ 
     split($0,D,/[^[:space:]]*/); 
     s = ""; 
     for(i=1;i<=NF;i++){ 
      if($i~/NoData/){ $i = last[i]; } 
      last[i]=$i ; 
      s = s sprintf("%s%s",D[i],$i) 
     } 
     print s 
}' file 

或通过设置OFS=""OFS=

awk -v OFS= '{ 
     split($0,D,/[^[:space:]]*/); 
     for(i=1;i<=NF;i++){ 
      if($i~/NoData/){ $i = last[i]; } 
      last[i]=$i ; 
      $i = sprintf("%s%s",D[i],$i) 
     } 
}1' file 

实施例 - 1(保留格式)

$ cat file 
0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 NoData 0.0357 0.3922 0.0462 
0.6324 0.1576 NoData NoData 0.6555 0.0971 
0.0975 0.9706 NoData NoData 0.1712 0.8235 

$ awk '{ 
     split($0,D,/[^[:space:]]*/); 
     s = ""; 
     for(i=1;i<=NF;i++){ 
      if($i~/NoData/){ $i = last[i]; } 
      last[i]=$i ; 
      s = s sprintf("%s%s",D[i],$i) 
     } 
     print s 
}' file 
0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 0.8003 0.0357 0.3922 0.0462 
0.6324 0.1576 0.8003 0.0357 0.6555 0.0971 
0.0975 0.9706 0.8003 0.0357 0.1712 0.8235 

实施例 - 2(不保留源格式)

默认情况下,它将单个空格作为输出分隔符,如果您设置了OFS,它将覆盖默认值。

$ cat file 
0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 NoData 0.0357 0.3922 0.0462 
0.6324 0.1576 NoData NoData 0.6555 0.0971 
0.0975 0.9706 NoData NoData 0.1712 0.8235 

$ awk '{for(i=1;i<=NF;i++){ if($i~/NoData/){ $i=last[i]; } last[i]=$i } }1' file 
0.8147 0.2785 0.9572 0.7922 0.6787 0.7060 
0.9058 0.5469 0.4854 0.9595 0.7577 0.0318 
0.1270 0.9575 0.8003 0.6557 0.7431 0.2769 
0.9134 0.9649 0.8003 0.0357 0.3922 0.0462 
0.6324 0.1576 0.8003 0.0357 0.6555 0.0971 
0.0975 0.9706 0.8003 0.0357 0.1712 0.8235 
+0

哇,快和短。最后的结果是什么? – Patrik

+0

@Patrik'1'默认操作'print $ 0'(打印当前行/记录/行),意思是它的真实可以是任何非零数字 –

+1

好的,谢谢。我认为保留格式不是优先事项,因为输出将被其他程序解析。没关系,只要有至少一个空间 – Patrik