세미콜론으로 구분된 데이터가 포함된 3개의 열이 있는 탭으로 구분된 파일이 있습니다. (3개 열의 3가지 조건을 모두 만족하는) 각 열의 값을 필터링하고 싶습니다: 1번째 열(<-0.5), 2번째 열(>1), 3번째 열(>2). 실제 데이터에는 여러 열이 있습니다.
입력하다
-0.6;0.14;-0.56;0.2 10.4;NA;5.1;2 3;1;4;3 A;B;C;D
-0.9;-0.16;-1.1 2.4;0.1;0.9 10;1;3 E;F;G
원하는 출력
-0.6;-0.56 10.4;5.1 3;4 A;C
-0.9 2.4 10 E
각 행에 대해 각 열의 값 개수는 필터링 전과 후가 동일해야 합니다.
답변1
여기 Perl에 관한 미친 것들이 있습니다.
perl -lane '
BEGIN {
@criteria = (
sub {shift() < -0.5},
sub {shift() > 1},
sub {shift() > 2},
)
}
@filtered = ();
for $i (0..$#F) {
push @filtered, join ";", grep {$criteria[$i]->($_)} split /;/, $F[$i];
}
print join " ", @filtered;
' file | column -t
-0.6;-0.56 10.4;5.1 3;4
-0.9 2.4 10
이는 귀하의 요구 사항을 더 정확하게 반영합니다.
perl -lane '
sub criteria {
$_[0] < -0.5 and
$_[1] > 1 and
$_[2] > 2
}
@data = map {[split /;/]} @F;
@filtered = map {[]} @F;
for ($i = 0; $i < @{$data[0]}; $i++) {
@tuple = map {$data[$_][$i]} (0..$#F);
if (criteria(@tuple)) {
push @{$filtered[$_]}, $tuple[$_] for (0..$#F);
}
}
print join " ", map {join ";", @$_} @filtered;
' file
답변2
통과하다 awk
:
처음 세 필드가 모든 컬렉션 구성원에 대한 기준을 충족하는지 테스트합니다. (필드를 분할
;
하고 각 쌍을 테스트)그렇다면 각 필드에서 컬렉션이 어디에 있는지 기억하세요. (배열에서
sel
)두 번째 블록에서는 모든 필드를 반복하고 이전 위치와 일치하는 값만 유지합니다.
일치하는 항목이 있으면 인쇄하세요.
BEGIN {FS=OFS="\t"} { #select IDs of value sets to be keept split($1,a,";") split($2,b,";") split($3,c,";") nsel=0 ; delete sel for ( i in a ) { if (a[i]+0<-0.5 && b[i]+0>1 && c[i]+0>2) { sel[++nsel]=i } } #if any: run through all fields and reselect if (nsel) { for (i=1 ; i<=NF ; i++) { split($i,a,";") $i=a[sel[1]] for (j=2 ; j<=nsel ; j++) { $i=$i";"a[sel[j]] } } } } #print only if any matching set was found nsel