조건(목록에 존재하는 경우)을 기반으로 데이터프레임의 행을 필터링하고 싶습니다. 나는 지금까지 이것을 시도했습니다. 그런데 예상치 못한 결과가 나왔습니다. 데이터가 복사되고 있지만 이해할 수 없습니다
#!/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
element
awk
변수가 아닙니다 .
쉘 변수의 값을 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
. 첫 번째 필드가 이 배열의 키이면 행을 인쇄합니다.