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의 세 번째 옵션은 제공하려는 다양한 비교 연산자에 대한 함수를 만든 다음 사용하는 것입니다.간접 함수 호출변수에 주어진 이름을 기반으로 그 중 하나를 호출하십시오.

예를 들어, 보다 작음 및 보다 큼 테스트의 경우:

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:

-에스프로그램 이름 뒤, 파일 이름 인수(또는 인수) 앞의 --명령줄에서 스위치의 기본 스위치 구문 분석을 활성화합니다 . 여기에서 발견된 모든 스위치는 @ARGVPerl 프로그램에서 제거되고 해당 변수가 설정됩니다. -xyz 스위치를 사용하여 다음 프로그램을 호출하면 "1"이 인쇄되고, -xyz=abc를 사용하여 프로그램을 호출하면 "abc"가 인쇄됩니다.

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

경고하다: eval잠재적으로 위험합니다. 제공할 수 있는 항목을 엄격하게 제어하지 않으면 $fn사용자가 스크립트를 실행하게 할 수 있습니다.어느펄 코드.

이것은 ~이 될 것이다많은사용자가 미리 정의된 제한된 연산자 집합에서만 선택할 수 있도록 하는 것이 더 안전합니다.

관련 정보