탭으로 구분된 다음과 같은 파일이 있습니다.
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
자세히보다.