Bash - 특정 비율의 열을 차지하는 행 필터링

Bash - 특정 비율의 열을 차지하는 행 필터링

그래서 나는 각각 8개의 열과 많은 행을 가진 많은 수의 파일을 가지고 있습니다. 다음은 그중 하나의 머리의 예입니다.

ID       Ct       1          2          3          4           5             6
1        0        consensus  -          -          -           -             -
2        0        consensus  -          -          -           -             -
3        0        consensus  consensus  consensus  consensus   consensus     consensus
4        0        consensus  -          consensus  -           -             -
5        0        -          AT         AT         GC          GC            AT
6        0        consensus  -          -          -           consensus     -
7        0        consensus  -          -          -           -             -
8        0        consensus  consensus  consensus  -           consensus     consensus
9        0        consensus  -          -          -           -             -

마지막 6개 열이 적어도 5/6 이상 차지하는 모든 행을 분리하고 싶습니다. 따라서 ID 3, 5, 8(4, 6, 9행)은 내 머리에서 나온 것입니다. 따라서 2개 미만의 열이 있는 모든 행에 "-"가 유효하도록 하고 싶습니다.

나는 프로그램이 두 번째 열에서 얼마나 많은 열을 차지했는지 계산했기 때문에 간단한 awk 스크립트를 사용하여 이 작업을 수행할 수 있었습니다. 더 이상 이 작업을 수행할 수 없는 것 같습니다. 가장 좋은 접근 방식은 무엇입니까?

답변1

얼마나 멀리 갈 것인가?

awk 'gsub(/-/, "&") < 2' file
ID       Ct       1          2          3          4           5             6
3        0        consensus  consensus  consensus  consensus   consensus     consensus
5        0        -          AT         AT         GC          GC            AT
8        0        consensus  consensus  consensus  -           consensus     consensus

이해합니다? rg는 아무 말도 하지 않습니다. 원하는 출력 - 단일 출력 파일, 출력 줄 앞에 파일 이름이 붙는 것, 원본 파일과 비슷한 이름을 가진 새 파일, 또는 무엇을 원하십니까?

편집하다(새 파일 이름에 주석을 단 후):

awk 'gsub(/-/, "&") < 2 {print > (FILENAME ".new")}' /path/to/file/*

답변2

모든 파일이 동일한 디렉터리에 있으면 for 루프/glob을 사용하여 각 파일을 반복하고 해당 파일에 대해 awk 명령을 실행할 수 있습니다.

for file in /path/to/files/*; do
    awk '{
        count=0
        for (i=3;i<=8;i++) {
            if ($i == "-") {
                count++
            }
        }
        if ((count <= 1)) {
            print
        }
    }' "$file"
done

각 행에 대해 3-8열을 반복하며 해당 열의 값이 -추가된 값 과 같으면 행의 값이 1보다 count크면 count인쇄되지 않습니다.

답변3

Perl은 이런 종류의 작업에 편리합니다. 특히 grep명시적인 루프 없이 필드별로 작업을 수행할 수 있으며 그 결과(스칼라 컨텍스트에서 평가할 때) 일치 횟수가 제공됩니다. 예를 들어

$ perl -lane 'print if 3 > grep { $_ eq "-" } splice @F, 2' file
ID       Ct       1          2          3          4           5             6
3        0        consensus  consensus  consensus  consensus   consensus     consensus
5        0        -          AT         AT         GC          GC            AT
8        0        consensus  consensus  consensus  -           consensus     consensus

관련 정보