AWKでIF文を使用する

AWKでIF文を使用する

私は大きなスクリプトを書いていますが、誰かが私を助けることができれば、この部分で詰まっていました。

サンプルファイルです

31:49.9,9.92,TCP ,1_19,490,EXT_SERVER,22,5,257,1,.ASF,0,normal

これは私のスクリプトの一部です

read -p "Please input the function itself ex, > : " function
read -p "Please input the value: " value

このように使うと私によく合う

cat temp | awk -F',' -v val="$value" '{if($8 > val) print $0}' > $destfile

しかし、このように使用しようとすると

cat temp | awk -F',' -v val="$value" -v fn="$function" '{if($8 fn val) print $0}' > $destfile

ありがとう

答え1

変数の内容に基づいて実行時に演算子を生成できるプログラミング言語はあまりありません。コードを分析するとき、if文の条件式は構文的に有効でなければなりませんが、そうではありません。$number variable variable

(もちろんシェルおよびtest/[またはegで行うことができますが、これはコマンドであり、その引数はシェルが変数を展開した後に解析されるため[ "$a" "$op" "$b" ]です。)[

あなたはいくつかの選択肢があります。

awkがコードを解析する前に、次のようにシェル拡張演算子を使用できます。

cat temp | awk -F',' -v val="$value" '
               {if($8 '"$function"' val) print $0}' > $destfile

その後、たとえば$function含まれている場合は、<awkでこれを見ることができます{if($8 < val) ...。これにより、$functionawkを実行する前に、その演算子が許容可能な演算子であることを確認する必要があります。そうしないと、ユーザーに信じられないほどの構文エラーが発生する可能性があります。


別のオプションとして、ユーザーは下限と上限を入力し、コードで常に両方を確認できます。ユーザーが下限/上限を別々に入力したくない場合は、たとえば、-inf十分に低い/高い値を別のものに置き換えます。+inf

read -p "Please enter lower limit: " lo
read -p "Please enter upper limit: " hi
cat temp | awk -F',' -v lo="${lo:--inf}" -v hi="${hi:-+inf}" '
               {if (lo <= $8 && $8 <= hi) print $0}' > $destfile

-inf/は+infGNU awkとBusyboxで直接動作しているようですが、mawkは同じ数字を使用するように強制する必要があるようですlo + 0 <= $8。)


私の考えでは、GNU awkの3番目のオプションは、提供したいさまざまな比較演算子の関数を作成して使用することです。間接関数の呼び出し変数に与えられた名前に基づいてそのうちの1つを呼び出します。

たとえば、より小さいテストとより大きいテストの場合:

read -p "Please input the function (lt or gt): " op
read -p "Please input the value: " value
cat temp | gawk -F',' -v op="$op" -v val="$value" '
                function lt(a, b) { return a < b; }
                function gt(a, b) { return a > b; }
                {if (@op($8, val)) print $0}'

もちろん、この方法の欠点は明示的に生成する必要があることです。みんな関数にユーザーが誤った関数名を入力すると、エラーが発生します。

答え2

1. awkスクリプトの修正sed

awkスクリプトを変数に保存し、awkが実行される前にsedを使用してそれを変更できます。例えば

#!/bin/bash

awkscript='COL FN VAL'

col=8
fn='>'
val=2 

awk -f <(printf "%s" "$awkscript" |
           sed -e "s/COL/\$$col/; s/FN/$fn/; s/VAL/$val/") temp

COL FN VALすると、「$awkscript」が$8 > 2

COL簡単に言うと、「awkスクリプト」は、ハードコードされたいくつかの文字列(、、およびFNVALを変数に置き換えるテンプレートです。

警告:変数にスクリプトの解釈方法/に影響を与える値が含まれている場合(例)、sed問題が発生する可能性がありますsed。テンプレートを作成するより安全で、より良い、より複雑な方法がありますが、変数が互換性があり、sedを破損しない値だけを維持できるようにする場合は、このような単純なテンプレートをお勧めします。

ファイルを使用するかトレドックawkスクリプトを保存します。

あるいは、非常に単純な実装の場合は次のようになります。

awk -f <(echo "$col $fn $val") temp

または

awk -f <(cat <<< "$col $fn $val") temp

2.使用perleval

perlawkの代わりにこの関数を使用してこれを実行できますeval

perl -F, -slne 'print if (eval "$F[7] $fn $val")' -- -val="$value" -fn='>' temp

でも:

perl -F, -slne 'print if (eval "$F[$col-1] $fn $val")'  -- \
  -col=8 -val="$value" -fn='<' temp

Perlの配列は0から始まるので、$F[7]withの代わりに$ 8を使用しますawk

Perl-sオプションを使用すると、Perlのawkに似た機能を使用してコマンドラインから変数を割り当てることができます。

からman perlrun

-Sプログラム名の後に、ファイル名引数(または引数)の前の--コマンドラインでスイッチのデフォルトのスイッチ解析を有効にします。ここで見つかったすべてのスイッチは@ARGVPerlプログラムから削除され、対応する変数が設定されます。 -xyzスイッチを使用して次のプログラムを呼び出すと「1」が印刷され、-xyz = abcを使用してプログラムを呼び出すと「abc」が印刷されます。

   #!/usr/bin/perl -s
   if ($xyz) { print "$xyz\n" }

警告する: eval潜在的に危険です。提供できる項目を厳密に制御しないと、$fnユーザーにスクリプトを実行させることができます。どのパールコード。

これは〜になりますたくさんユーザーが事前定義された制限された演算子のセットからのみ選択できるようにする方が安全です。

関連情報