使用awk

时间:2019-03-18 11:51:58

标签: vim awk

我必须用其他数字替换列中数字的第一个实例。
这就是我要做的

输入:

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 76 78  
77 564 65 76 45 

输出:

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78  
77 564 65 76 45  

因此,在第四列中首次出现的7691取代。
这就是我尝试使用awk进行的操作:

awk '{count=0;if ($4 == 76 && count < 1){ gsub("91","76")} count++; print}' input > output 

但这没有帮助,有人可以提出建议吗?

6 个答案:

答案 0 :(得分:4)

stack0114106's answer进行一些调整,使其更加简洁:

awk '!t && $4==76 { $4=91; t=1;} 1 ' file

awk中未分配的变量将具有0或空字符串值,将其取反将得到true
并且我将!t放在另一个比较方程式之前是为了提高效率,因为&&是一种快捷运算符,当第一部分的计算结果为false时,它将阻止第二部分的执行。

最后一个1将在此处产生true,一个无块的条件将隐含{print $0}块。

答案 1 :(得分:3)

请您尝试以下操作(使用这种方法,我们提到的是变量中的所有值,没有任何硬编码,因为任何进一步的值更改只需更改变量值,程序就可以正常工作。)

awk -v column="4" -v count="1" -v value="76" -v new_value="91" '($column == value){if(++num==count){$column=new_value}} 1' Input_file

或添加非单一衬里形式的解决方案。

awk -v column="4" -v count="1" -v value="76" -v new_value="91" '
($column == value){
  if(++num==count){
      $column=new_value
  }
}
1
'  Input_file

输出如下。

54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78
77 564 65 76 45


编辑: :更正OP'尝试并添加更正详细信息。

代码应更改为:

awk '{if ($4 == 76){if(++count == 1){sub("^" 76 "$","91",$4)}};print}' Input_file

OP的代码上面的FIX解释:

  • count=0在这里是一个错误,因为每次读取新行时,它将使变量count的值变为0,程序将永远不知道76在第4个字段中出现了多少次,因此我删除了它。
  • 现在位置count<0实际上应该是++count==1并且应该位于条件$4==76的块内,为什么因为前夕条件不是TRUE($4==76)变量计数的值是继续增加,所以让我们增加,然后在条件$4==76为TRUE时,它将正确保持其计数。
  • 现在我更正了gsub,即使是固定的,仍然无法执行代码,原因是(g)sub模式为sub(current_value,replaced_value),所以您用91替换了76与您的要求完全相反,在执行此FIX之后,您的代码应该可以正常工作:)

答案 2 :(得分:2)

尝试这个简单的awk

awk -v t=1 ' $4==76 && t==1 { $4=91; t=0;} 1 ' file

要纠正您的尝试,只需将count的初始化包装在BEGIN块中并交换匹配项并替换gsub中的输入,即76和91

awk ' BEGIN {count=0; } { if ($4 == 76 && count < 1){ gsub("76","91"); count++; } print}  ' input > output 

使用您的输入

$ cat himanshu.txt
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 76 78
77 564 65 76 45

$ awk -v t=1 ' $4==76 && t==1 { $4=91; t=0;} 1 ' himanshu.txt
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45

$

答案 3 :(得分:1)

如果您的awk值可以位于任何列中,则可以使用以下76命令:

awk '{for(i=1;i<=NF;i++){if($i == 76 && count < 1){count++; $i=91}}print}' input
54 679 75 98 21  
24 543 86 98 43  
42 543 54 98 55  
93 255 25 98 25  
43 523 43 98 31  
98 775 24 91 78
77 564 65 76 45

答案 4 :(得分:1)

您的标题令人困惑:您想从gvim调用awk来编辑当前正在编辑的文件吗?在vim中做

  1. 跳转到文件顶部: g g
  2. 在第四个字段中搜索76: / ^[^ ]\+ [^ ]\+ [^ ]\+ 76 输入
  3. 跳转到第四个字段: 3 w
  4. 更改单词: c w 91 Esc

答案 5 :(得分:1)

这是我的解决方法

awk -v count=0 -v replace=76 -v replaceWith=91 'count==0&&$4==76{gsub("^" replace "$", replaceWith, $4); count++}1' sourceFile

使用了三个变量countreplacereplaceWith count用于计算搜索词的出现次数。在找到搜索词replace之后,我增加了自己的代码,并确保没有借助表达式count == 0

重新回到该操作中

replace可以是列表中的任何值...不必进行硬编码。 与replaceWith相同,您希望将值替换为

结果

awk -v count=0 -v replace=76 -v replaceWith=91  'count==0&&$4==76{sub("^" replace "$", replaceWith, $4); count++}1' sourceFile
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45

在收到以下反馈后更改了脚本。将gsub替换为$4 = replaceWith

awk -v count=0 -v replace=76 -v replaceWith=91 'count==0 && $4==replace{$4 = replaceWith; count++}1' sourceFile
54 679 75 98 21
24 543 86 98 43
42 543 54 98 55
93 255 25 98 25
43 523 43 98 31
98 775 24 91 78
77 564 65 76 45