동일한 열 값 제거

동일한 열 값 제거

매우 큰 파일이 있는데 열 값이 9이면 삭제하고 싶습니다.

견본:

내 파일 값은 다음과 같습니다

1 5 8 3 5 9 5 7 6 9
2 5 7 4 2 9 7 6 3 1
5 9 7 4 1 9 5 7 9 1

모든 행에서 값이 9인 열을 제거하고 싶습니다(열 크기가 너무 커서 첫 번째 열 = 9, 두 번째 열 = 9...등을 확인할 수 없습니다). 동적 스크립트가 필요합니다.

출력은 다음과 같아야 합니다.

1 5 8 3 5 5 7 6 9
2 5 7 4 2 7 6 3 1
5 9 7 4 1 5 7 9 1

나는 새로운 사람이고 많은 것을 시도했지만 제대로 이해하지 못했습니다.

어떻게 해야 합니까?

당신의 도움을 주셔서 감사합니다

답변1

파이썬에서는:

#! /usr/bin/env python3

import sys
# Get the numbers
numbers = [[int(x) for x in line.strip().split()] for line in sys.stdin] 
# Get indexes of 9 in sets for each row
index_9 = (set(x for x, num in enumerate(line) if num == 9) for line in numbers)  

common_column = next(index_9).intersection(*index_9)

for line in numbers:
    print(' '.join((str(num) for x, num in enumerate(line) if x not in common_column)))

답변2

awk방법은 각 행에 동일한 수의 필드가 있다고 가정합니다(질문에 제공된 예에 표시된 대로). 또한 빈 필드가 없다고 가정합니다.

cat <<EOF >file
1 5 8 3 5 9 5 7 6 9
2 5 7 4 2 9 7 6 3 1
5 9 7 4 1 9 5 7 9 1
EOF

awk '{ for (c=1; c<=NF; c++) a[NR,c]=$c }
 END { for (c=1; c<=NF; c++) { 
         vc="" # values in column
         for (r=1; r<=NR; r++) { 
           vc = vc " " a[r,c]  }
         if ( ! gensub( /[9 ]/,"","g",vc) ) {
           for (r=1; r<=NR; r++) {
             a[r,c] = "" } }
       }
       for (r=1; r<=NR; r++) {
         for (c=1; c<=NF; c++) {
           if ( a[r,c] ) printf a[r,c]" " } 
         print "" }
     }' file

# output
1 5 8 3 5 5 7 6 9 
2 5 7 4 2 7 6 3 1 
5 9 7 4 1 5 7 9 1

답변3

많은 저장 공간이 필요하지 않은 bash/GNU coreutils를 사용하는 가능한 방법은 다음과 같습니다.

  1. cut파일을 열별로 기록하고 전체가 9로 구성되지 않은 열의 인덱스를 기록합니다. 파일에 포함된 열 수(이 경우 10)를 알고 있으면 간단할 수 있습니다.

    for ((i=1;i<11;i++)); do 
      [[ $(cut -d' ' -f${i} file | sed '/^9$/d' | wc -l) -eq 0 ]] || a+=($i)
    done
    

    (9를 모두 제거한 후 전체가 9로 구성된 열만 길이가 0이라는 사실을 이용)

  2. 유지될 열 목록을 추가 cut명령에 전달하고 변경 사항을 사용하여 IFS배열을 쉼표로 구분된 목록으로 변환합니다.

    (IFS=, ; cut -d' ' -f"${a[*]}" file)
    

귀하의 버전이 cut--complement플래그를 지원하는 경우 다음 열을 기록할 수 있습니다.하다다음을 제외한 모든 9와 cut모든 항목을 포함합니다.

    for ((i=1;i<11;i++)); do
      [[ $(cut -d' ' -f${i} file | sed '/^9$/d' | wc -l) -eq 0 ]] && a+=($i)
    done

    (IFS=, ; cut -d' ' --complement -f"${a[*]}" file)

답변4

질문의 정보를 바탕으로 현재 알아낼 수 있는 내용은 다음과 같습니다.

awk '{for (i=1; i<NF; i++){ a[i]+=$i; b[i]=b[i]" " $i}} END{for (i=1; i<NF; i++) if (a[i]/NR!=9) {printf "%s\n", b[i]}}' same-column-values

이 함수는 파일 전체를 반복하고 합계를 변수 "a"로 계산한 다음 해당 값을 인덱스 배열 "b"에 추가합니다. 파일을 완전히 읽은 후 합계 배열이 반복되고 합계를 레코드 수(NR)로 나눈 값이 9와 같지 않으면 배열 "b"의 해당 행이 인쇄됩니다.

이것은 나에게 출력을 제공합니다 1 2 5 5 5 9 8 7 7 3 4 4 5 2 1 5 7 5 7 6 7 6 3 9

단점은 출력을 위에서 아래로 읽어야 하고 위에서 아래로, 왼쪽에서 오른쪽으로 변환해야 한다는 것입니다.

또는 다음 명령을 사용하여 값 9만 포함된 열 목록을 가져올 수 있습니다.

awk '{for (i=1; i<NF; i++){ a[i]+=$i; b[i]=b[i]" " $i}} END{for (i=1; i<NF; i++) if (a[i]/NR==9){print i; }}' same-column-values

관련 정보