파일에 NULL 값이 모두 포함된 열을 표시하지 않는 방법

파일에 NULL 값이 모두 포함된 열을 표시하지 않는 방법

예를 들어 5개의 열이 있는 파일이 있습니다(Sybase 선택 쿼리의 결과를 리디렉션하여 얻음). 각 열은 탭 문자로 구분됩니다. 모든 NULL 열을 필터링해야 합니다. 5개 열 중 하나라도 비어 있을 수 있습니다.

예를 들어, 파일의 열이 다음과 같은 경우:

1000    NULL    NULL    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL
7       NULL    1000    2       NULL

출력은 (열 2와 5를 제거한 후) 가급적 동일한 파일에 있어야 합니다.

1000    NULL    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2    
7       1000    2 

나는 도착했다:

for i in {1..5}  
do
echo $i
dlr="$"$i
str="{print $dlr}"
echo $str
awk '$str' <input_file> | while read value
    do
        echo $value

        if [ "$value" == "NULL" ]
        then
                echo "inside"
                cut $i 
        fi
    done
done

현재 값은 모든 행을 표시합니다! 그리고 기둥을 자르는 방법도 모르겠습니다. 저는 쉘 스크립팅 초보자인데 계속 진행할 수 없습니다.

이 작업을 수행하는 방법을 제안해 주실 수 있나요?

답변1

의 도움으로GNU 유틸리티datamash, 먼저 행을 뒤집은 다음 모든 빈 행을 제거하고 다시 행을 뒤집습니다.

$ datamash transpose | sed -Ee '/^(NULL\t)*NULL$/d' | datamash transpose 

답변2

나는 이 솔루션이 별로 마음에 들지 않지만 작동하는 것 같습니다.

#!/bin/bash

input=~/tmp/input
skip=()

c=$(awk '{print NF;exit}' "$input")

for ((i=1;i<=c;i++)); do
    col=$(awk -v c="$i" '{print $c}' "$input" | sort -u)
    if [[ $col == NULL ]]; then
        skip+=( "$i" )
    fi
done
( IFS=,; awk -v S="${skip[*]}" '{ split(S,s,","); for (i=1;i<=length(s);i++) { $s[i]="" } print}' "$input" )
  1. input(입력 파일)
  2. skip(나중에 채워질 배열)
  3. c(파일의 열 수로 설정됩니다. 이는 파일 전체의 열 수가 균일하다고 가정합니다.)
  4. 이제 파일의 각 열을 반복하여 정렬하고 고유한 다음 해당 열에 .만 포함되어 있는지 확인합니다 NULL. 그렇다면 해당 열 번호를 skip배열 에 추가합니다.
  5. 이제 쉼표로 설정하고 IFS(이것이 제가 서브쉘을 사용하는 이유입니다) skip배열을 쉼표로 구분된 값으로 awk변수에 전달합니다. 이를 사용하여 split해당 변수를 다시 배열로 변환 할 수 있습니다 awk.
  6. awks그런 다음 배열의 각 숫자를 반복 하고 열을 비우도록 설정한 후 나머지를 인쇄합니다.

답변3

파일을 두 번 처리하지 않고서는 이 작업을 수행할 수 없습니다. 먼저 다음 을 사용하여 awk최종 cut명령을 빌드합니다.

killnulls(){
    cut -f "$(awk -F'\t' '
        { for(i=1;i<=NF;i++) a[i] += $i!="NULL" }
        END { for(i=1;i in a;i++) if(a[i]) printf j++?","i:i }
    ' "$@")" "$@"
}

$ killnulls file
1000    NULL    2
7       1000    2
7       1000    2
...

답변4

주문하다:

awk '/NULL/{gsub(/NULL/,"",$0);print $0}' filename| sed -r "s/\s+/ /g"| awk 'NR==1{$3=$2;$2="NULL";}1'

산출

awk '/NULL/{gsub(/NULL/,"",$0);print $0}' i.txt| sed -r "s/\s+/ /g"| awk 'NR==1{$3=$2;$2="NULL";}1'
1000 NULL 2
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2 
7 1000 2

관련 정보