다른 행이 현재 행으로 시작하는 경우 행 삭제(열 기준)

다른 행이 현재 행으로 시작하는 경우 행 삭제(열 기준)

다음과 같이 input.txt 파일이 있습니다.상표구분 형식:

aaaa    bbbb
aaaa    bbbb    c
aaaa    bbbb    c   dd
aaaa    bbbb    cc
aaaa    bbbb    x
aaaa    bbbb    xx
dddd    eeee
dddd    eeee    f
dddd    eeee    f   g
dddd    eeee    fe
h   ii  j

각 행에 대해 다른 행에 이미 선행 열이 포함되어 있는지 확인하세요. 그렇다면 해당 줄을 삭제하세요. 그렇지 않으면 이 예를 살펴보겠습니다.

  • 첫 번째 열이 동일한 추가 열이 포함된 다른 행(2행)이 있으므로 첫 번째 행이 삭제됩니다. 이 경우 첫 번째 행을 삭제하고 두 번째 행을 유지하세요.
  • 동일한 첫 번째 열이 있는 추가 열이 포함된 다른 행(세 번째 행)이 있기 때문에 두 번째 행이 삭제됩니다. 이 경우 두 번째 행을 삭제하고 세 번째 행을 유지하세요.
  • 동일한 첫 번째 열이 있는 다른 행이 없기 때문에 세 번째 행은 삭제되지 않습니다. 이 경우 세 번째 행을 유지합니다.

기타 등등 출력 파일은 다음과 같아야 합니다.

aaaa    bbbb    c   dd
aaaa    bbbb    cc
aaaa    bbbb    x
aaaa    bbbb    xx
dddd    eeee    f   g
dddd    eeee    fe
h   ii  j

수백만 개의 행을 원활하게 실행할 수 있는 솔루션을 찾을 수도 있습니다.

답변1

이것은 단지 입력을 역순으로 정렬하므로 "foobar"가 "foo" 앞에 오게 됩니다. 이는 현재 줄(foo)이 각 줄의 첫 번째 문자로 시작하는 이전 줄(foobar)의 하위 문자열인 경우에는 발생하지 않습니다. 현재를 인쇄합니다. 라인 (foo).

$ sort -r file | awk 'index(prev FS,$0 FS) != 1; {prev=$0}'
h   ii  j
dddd    eeee    fe
dddd    eeee    f   g
aaaa    bbbb    xx
aaaa    bbbb    x
aaaa    bbbb    cc
aaaa    bbbb    c   dd

출력 순서가 중요한 경우 이 문제를 해결하는 방법에는 여러 가지가 있습니다. 예를 들면 다음과 같습니다.

$ cat -n file | sort -k2r |
    awk '{orig=$0; $1=""} index(prev FS,$0 FS) != 1{print orig} {prev=$0}' |
    sort -n | cut -f2-
aaaa    bbbb    c   dd
aaaa    bbbb    cc
aaaa    bbbb    x
aaaa    bbbb    xx
dddd    eeee    f   g
dddd    eeee    fe
h   ii  j

답변2

문자가 아닌 열(필드)을 기준으로 다른 행의 접두사인 행을 삭제하려고 합니다. 이는 awk(1)을 사용하여 달성할 수 있습니다. 먼저 긴 행이 먼저 오도록 데이터를 역순으로 정렬합니다. 따라서 행이 접두사인 경우 해당 행이 접두사가 됩니다. 그런 다음 awk를 사용하여 필드를 스캔하여 저장한 마지막 행과 일치하는지 확인하고 그렇다면 삭제할 수 있습니다.

sort -r input.txt | awk '
    { for (i=1; i<=NF; i++) if (save[i] != $i) {keep=1; break} }
    keep == 0 { next }
    { delete save; for (i=1; i<=NF; i++) save[i]=$i; keep=0; print }
'

첫 번째 awk 작업은 현재 필드를 저장된 필드 세트와 비교합니다. 필드 중 하나라도 다른 경우 해당 라인을 키퍼로 표시합니다. 모두 같으면 우리는 아니므로 두 번째 동작이 적용되고 골키퍼가 아니면 라인을 건너뜁니다. 세 번째 작업은 현재 줄을 저장하고 인쇄하여 다음 줄을 준비하기 위해 보류 플래그를 지웁니다.

수백만 행 길이의 데이터세트가 없으므로 이것이 효과가 있을지 잘 모르겠습니다. 한번 해보고 확인해 보세요.

답변3

줄의 시작 부분에 고정된 패턴에서 가장 길고 고유한 일치 항목을 찾고 있으므로 파일 이름이 tst라고 가정합니다....

while read l ; do if [ $(grep -c -E "^$l" tst) -eq 1 ]; then echo $l; fi ; done < tst

다만, 가장 긴 패턴이 반복되면 실패하므로 이를 처리해야 합니다...

while read l ; do if [ $(grep -c -E "^$l" <<<$(sort tst | uniq)) -eq 1 ]; then echo $l; fi ; done <<<$(sort tst | uniq)

관련 정보