私は大きなスクリプトを書いていますが、誰かが私を助けることができれば、この部分で詰まっていました。
サンプルファイルです
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) ...
。これにより、$function
awkを実行する前に、その演算子が許容可能な演算子であることを確認する必要があります。そうしないと、ユーザーに信じられないほどの構文エラーが発生する可能性があります。
別のオプションとして、ユーザーは下限と上限を入力し、コードで常に両方を確認できます。ユーザーが下限/上限を別々に入力したくない場合は、たとえば、-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
/は+inf
GNU 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スクリプト」は、ハードコードされたいくつかの文字列(、、およびFN
)VAL
を変数に置き換えるテンプレートです。
警告:変数にスクリプトの解釈方法/
に影響を与える値が含まれている場合(例)、sed
問題が発生する可能性がありますsed
。テンプレートを作成するより安全で、より良い、より複雑な方法がありますが、変数が互換性があり、sedを破損しない値だけを維持できるようにする場合は、このような単純なテンプレートをお勧めします。
ファイルを使用するかトレドックawkスクリプトを保存します。
あるいは、非常に単純な実装の場合は次のようになります。
awk -f <(echo "$col $fn $val") temp
または
awk -f <(cat <<< "$col $fn $val") temp
2.使用perl
とeval
perl
awkの代わりにこの関数を使用してこれを実行できます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プログラム名の後に、ファイル名引数(または引数)の前の
--
コマンドラインでスイッチのデフォルトのスイッチ解析を有効にします。ここで見つかったすべてのスイッチは@ARGV
Perlプログラムから削除され、対応する変数が設定されます。 -xyzスイッチを使用して次のプログラムを呼び出すと「1」が印刷され、-xyz = abcを使用してプログラムを呼び出すと「abc」が印刷されます。#!/usr/bin/perl -s if ($xyz) { print "$xyz\n" }
警告する: eval
潜在的に危険です。提供できる項目を厳密に制御しないと、$fn
ユーザーにスクリプトを実行させることができます。どのパールコード。
これは〜になりますたくさんユーザーが事前定義された制限された演算子のセットからのみ選択できるようにする方が安全です。