awk BEGIN比较if语句中的多个变量

时间:2017-03-31 08:19:32

标签: bash awk

我正在尝试比较bash中的一些浮点数/版本号,我正在使用awk BEGIN和if语句。 当我使用2个变量时,我能够进行比较并获得正确的输出。 但是在3个变量的情况下,我无法获得输出。

目标

我想要实现的是输入是否介于两个值4.8.0& 4.10.0,(即 4.8.0< = inp< 4.10.0 )然后输出1,否则输出0。

代码阻止

以下是我写的:

inp=4.9.4
out=`awk -v n1=$inp -v n2=4.8.0 -v n3=4.10.0 \
  'BEGIN {if (n1<n2) printf (0); else if (n1<n3) printf (1); else printf (0);}'`

我尝试的另一种方式是与多种情况进行比较

inp=4.9.4
out=`awk -v n1=$inp -v n2=4.8.0 -v n3=4.10.0 \
  'BEGIN {if (n1>n2 && n1<n3) printf (1); else printf (0);}'`

查询: 请帮助我如何使用awk BEGIN实现相同的效果? 如果还有其他方法可以比较浮动输入吗?

2 个答案:

答案 0 :(得分:1)

如果您的sort支持版本排序,则可以使用此快速机制:

if [ $(printf "%s\n" 4.8.0 "$inp" 4.10.0 | sort -V | awk NR==2 ) == "$inp" ]; then
    : Do something
fi

答案 1 :(得分:1)

问题不在于“&lt;”本身但字符串比较元素 4.9比4.10更大(字符串的观点)。在这种情况下,您必须将 4.09 与4.10进行比较 所以将输入转换为comparaison的相同顺序,这取决于您的版本控制的上下文

inp=4.9.0
out = $(
 awk -v nt=${inp} -v nl=4.8.0 -v nh=4.10.0 \
  '# use a function to compare dotted value 
    function lt( Arg1, Arg2) {
      # split version into elements
      S = ES1 = split( Arg1, E1, /[.]/)
      ES2 = split( Arg2, E2, /[.]/)
      # take longest serie
      if( ES1 < ES2) S = ES2
      # reinit lower and bigger flag
      l=b=0

      # test if bigger, smaller or equivalent
      for( i=1;i <= S && ! ( l || b ) ; i++) {
         if( E1[i] < E2[i] ) l++
          else if ( E1[i] > E2[i] ) b++
         }
      # return 1 if smaller
      return ( l )
      }

   # is between
   BEGIN { print ( lt(nl, nt) && lt( nt, nh)) }
   '
   )

请注意:

  • 分割虚线元素的功能,数字尽可能比较为数字
  • 还会比较更长或更短的版本号(空等效元素被视为0)