AWK를 사용하여 목록을 기반으로 데이터세트 필터링

AWK를 사용하여 목록을 기반으로 데이터세트 필터링

조건(목록에 존재하는 경우)을 기반으로 데이터프레임의 행을 필터링하고 싶습니다. 나는 지금까지 이것을 시도했습니다. 그런데 예상치 못한 결과가 나왔습니다. 데이터가 복사되고 있지만 이해할 수 없습니다

#!/bin/bash
arr_country=(AL AD AM AT BY BE BA BG CH)
for element in "${arr_country[@]}"
do
awk -F '\t' '{if($1==$element){print}}'   abc.txt >>xyz.txt
done
echo
echo "Data Transferred"

예제 데이터 세트에는 여러 국가에 대한 정보가 포함되어 있으며 첫 번째 열은 국가 이름을 나타냅니다. 주어진 배열을 기반으로 데이터세트의 하위 집합을 만들고 싶습니다.

답변1

elementawk변수가 아닙니다 .

쉘 변수의 값을 awk스크립트로 가져오려면 다음을 사용할 수 있습니다.

awk -v variable="$value" '{ script goes here }'

위의 예에서 이라는 변수는 variable이라는 셸 변수의 값을 가져옵니다 value. 접두사 없이 스크립트 variable에서 사용할 수 있습니다 .awk$

$변수 앞에 in 을 붙이면 awk변수 값이 양의 정수이고 현재 입력 레코드의 특정 필드를 참조하는 것으로 가정됩니다. $element예를 들어, 이 표현식은 필드 번호의 값을 제공합니다 element(예: $1첫 번째 필드의 값을 제공하고 $NF마지막 필드의 값을 제공합니다. 여기서 는 NF현재 레코드의 필드 수를 나타내는 내장 변수입니다) ).

element코드에 설정하지 않으면 awk전체 줄로 확장 $element됩니다 . $0탭으로 구분된 첫 번째 필드가 줄의 유일한 항목인 경우 코드는 전체 줄을 인쇄합니다.

스크립트 awk를 다음과 같이 단축할 수도 있습니다.

awk -F '\t' -v e="$element" '$1 == e'

또는 전체 콘텐츠를 다음으로 바꿀 수 있습니다.

arr_country=(AL AD AM AT BY BE BA BG CH)

( IFS='|'; grep -E "^(${arr_country[*]})\>" ) <abc.txt >xyz.txt

또는,

grep -E '^(AL|AD|AM|AT|BY|BE|BA|BG|CH)\>' <abc.txt >xyz.txt

매개변수 ${arr_country[*]}대체는 의 첫 번째 문자로 구분된 배열 값으로 구성된 단일 문자열로 확장됩니다 $IFS. 그러면 위에 표시된 두 번째 정규식과 동일한 정규식이 생성됩니다 grep. \>단어 끝의 너비가 0인 공백과 일치합니다( 줄의 시작 부분 ^AA\>과 일치 AA하지만 줄의 시작 부분과는 일치하지 않음 AAA).

유일한 차이점은 쉘 루프 솔루션과 비교하여 결과의 ​​순서가 다를 수 있다는 것입니다 awk.


쉘 루프를 제거하는 다양한 방법(기본값으로 가정 $IFS):

arr_country=(AL AD AM AT BY BE BA BG CH)

awk -v c="${arr_country[*]}" -F '\t' '
    BEGIN { n=split(c,a," "); for (i=1;i<=n;++i) country[a[i]] }
    $1 in country' <abc.txt >xyz.txt

arr_country여기서는 공백으로 구분된 문자열 의 요소를 awk변수의 코드 에 할당합니다 c. 입력에서 읽기를 시작하기 전에 c문자열은 여러 부분으로 나누어지고 각 부분은 연관 배열의 키로 만들어집니다 country. 첫 번째 필드가 이 배열의 키이면 행을 인쇄합니다.

관련 정보