awk를 사용하여 행 필터링

awk를 사용하여 행 필터링

탭으로 구분된 다음과 같은 파일이 있습니다.

name    v1  v2  v3  v4
g1  4.5 2.3 2.1 0.2
g2  10  3   5   2.3
g3  7   2.5 2.8 3.9

5개의 열과 4개의 행(헤더 포함)이 있는 더미 파일이 표시됩니다. 행을 필터링하고 특정 행의 각 열 값이 2보다 크면 해당 행을 유지하고 그렇지 않으면 삭제합니다. 출력은 다음과 같아야 합니다.

name    v1  v2  v3  v4
g2  10  3   5   2.3
g3  7   2.5 2.8 3.9

awk를 사용하여 이 작업을 어떻게 수행할 수 있나요?

답변1

AFAIK awk는 필드를 명시적으로 반복할 수 있는 방법이 없습니다. 예를 들어:

$ awk 'NR>1 {for(i=2;i<=NF;i++) if($i+0 < 2) next} 1' file
name    v1  v2  v3  v4
g2  10  3   5   2.3
g3  7   2.5 2.8 3.9

답변2

Steeldriver는 이미 awk 솔루션을 제공합니다. 다음은 Perl 버전입니다(for 루프 대신 배열 슬라이스 사용).

$ perl -lane 'print if ($.==1 || grep ($_ >= 2, @F) == $#F)' input.txt
name    v1  v2  v3  v4
g2  10  3   5   2.3
g3  7   2.5 2.8 3.9

이렇게 하면 첫 번째 행(헤더)만 인쇄되고 숫자 필드 값이 2보다 크거나 같은 모든 행이 인쇄됩니다. ( g1또는 와 같은 숫자가 아닌 필드 g2는 으로 계산됩니다 0.)


참고: Perl의 기능은 개념적으로 유사하지만 grep()명령줄 프로그램과 정확히 동일하지는 않습니다.grep

grep(expression,array)$_ >= 2첫 번째 인수에서 표현식을 실행합니다(예:)배열의 각 요소(예 @F: ), 결과가 true인 각 요소로 구성된 배열을 반환합니다.

스칼라 컨텍스트(예: 정수를 사용한 숫자 비교)에서는 배열이 아닌 식이 true인 횟수를 반환합니다. 이것이 우리가 여기서 하는 일입니다 . (배열의 요소 수 )와 동등성을 == $#F테스트하기 위한 것입니다 .$#F@F

표현식은 이 예제에서 사용된 것과 같은 간단한 테스트일 수도 있고 Perl 코드를 포함하는 코드 블록일 수도 있습니다. 또한 각 요소를 수정할 수 있는 옵션도 있습니다. 예를 들어, @new = grep(s/foo/bar/g, @old)@new는 성공적으로 수정된 @old의 모든 요소로 채워집니다(즉, 최소한 하나의 "foo"를 포함하는 thost. 모든 요소는 "bar"로 변경됨). perldoc -f grep자세히보다.

관련 정보