如果awk里面的语句改变了一个值

时间:2014-01-23 19:53:55

标签: perl if-statement awk

我有以下文件

...
MODE P E
IMP:P 1 19r 0
IMP:E 1 19r 0
...
SDEF POS= 0 0 14.6 AXS= 0 0 1 EXT=d3 RAD= d4 cell=23 ERG=d1 PAR=2
SI1 L  0.020
SP1    1
SI4 0. 3.401                                                                    
SI3 0.9 
...
NPS 20000000

我想做以下任务

  1. 检查序列ERG=后是否有数字或字符串。
  2. 如果是字符串,请找到序列SI1 L并使用用户输入的值更改之后的值。
  3. 如果是数字,请使用用户输入的值更改数字。
  4. 请注意,如果在ERG=之后有一个数字,则不会有SI1 L个序列。

    例如,数字2可以使用以下

    来完成
    #! /bin/bash
    
    vals=(0.02 0.03 0.04 0.05)
    
    for val in "${vals[@]}"; do
      awk -vval="$val" '$1=="SI1"{$3=val}1' 20
    done
    

    如何实现上述算法?

2 个答案:

答案 0 :(得分:1)

awk -F '[[:blank:]=]' -v string_value="foo" -v number_value=42 '
    /ERG=/ { 
        for (i=1; i<NF; i++)
            if ($i == "ERG") {
                isstring = ($(i+1) ~ /[^[:digit:]]/)
                break
            }
        if (!isstring)
            $(i+1) = number_value
    }
    /SI1 L/ && isstring { $NF = string_value }
    1
' filename

答案 1 :(得分:1)

  #!/bin/bash

val="$@"

awk -v val="$val" '
  BEGIN { i=1; split (val,v," ") }
  # If it is a string, find the sequence SI1 L and change the value after that, using values that the user inputs
  /SDEF POS.*ERG=[a-zA-Z]+/ { flag="y" ; }
  /SI1 L/ { if (flag=="y") { $3=v[i]; i++; flag="n"; } }
  # If it is a number, change the number using values that the user inputs.
  /SDEF POS.*ERG=[0-9]+ / { sub(/ERG=[0-9]*/, "ERG="v[i],$0);i++; }
  1
' file

提示:

如果规则找到至少包含一个或多个字母的ERG([a-zA-Z] +,则会设置该标志。 如果设置了标志,则/ SI1 L /规则将仅触发。如果规则被触发,它将再次取消设置标志,以便任何后续/ SI L /不会再次触发。

。*代表0-n符号或字符

[A-Za-z] +代表小写或大写的1-n字母字符