예를 들어 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" )
input
(입력 파일)skip
(나중에 채워질 배열)c
(파일의 열 수로 설정됩니다. 이는 파일 전체의 열 수가 균일하다고 가정합니다.)- 이제 파일의 각 열을 반복하여 정렬하고 고유한 다음 해당 열에 .만 포함되어 있는지 확인합니다
NULL
. 그렇다면 해당 열 번호를skip
배열 에 추가합니다. - 이제 쉼표로 설정하고
IFS
(이것이 제가 서브쉘을 사용하는 이유입니다)skip
배열을 쉼표로 구분된 값으로awk
변수에 전달합니다. 이를 사용하여split
해당 변수를 다시 배열로 변환 할 수 있습니다awk
. awk
s
그런 다음 배열의 각 숫자를 반복 하고 열을 비우도록 설정한 후 나머지를 인쇄합니다.
답변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