저는 큰 스크립트를 작성하고 있는데 누군가 저를 도와줄 수 있다면 이 부분에서 막혔습니다.
샘플 파일입니다
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의 세 번째 옵션은 제공하려는 다양한 비교 연산자에 대한 함수를 만든 다음 사용하는 것입니다.간접 함수 호출변수에 주어진 이름을 기반으로 그 중 하나를 호출하십시오.
예를 들어, 보다 작음 및 보다 큼 테스트의 경우:
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
:
-에스프로그램 이름 뒤, 파일 이름 인수(또는 인수) 앞의
--
명령줄에서 스위치의 기본 스위치 구문 분석을 활성화합니다 . 여기에서 발견된 모든 스위치는@ARGV
Perl 프로그램에서 제거되고 해당 변수가 설정됩니다. -xyz 스위치를 사용하여 다음 프로그램을 호출하면 "1"이 인쇄되고, -xyz=abc를 사용하여 프로그램을 호출하면 "abc"가 인쇄됩니다.#!/usr/bin/perl -s if ($xyz) { print "$xyz\n" }
경고하다: eval
잠재적으로 위험합니다. 제공할 수 있는 항목을 엄격하게 제어하지 않으면 $fn
사용자가 스크립트를 실행하게 할 수 있습니다.어느펄 코드.
이것은 ~이 될 것이다많은사용자가 미리 정의된 제한된 연산자 집합에서만 선택할 수 있도록 하는 것이 더 안전합니다.