모든 행의 두 번째 필드에 동일한 첫 번째 필드에 대한 값이 있는 경우 인쇄

모든 행의 두 번째 필드에 동일한 첫 번째 필드에 대한 값이 있는 경우 인쇄

공백으로 구분된 두 개의 열이 있는 파일이 있습니다. 두 번째 열에 T는 or 중 하나만 있습니다 F. 첫 번째 열의 문자를 읽고 싶습니다. 예를 들어 A두 번째 열에 동일한 문자가 있는 3개의 행이 있으면 유지하지만 두 번째 열에 혼합 문자가 있는 경우 제거됩니다.TABD

A T
A T
A T
B T
B T
B F
C F
C F
D F
D T
D F

두 번째 필드에 동일한 첫 번째 필드의 모든 행에 값이 있으면 인쇄하고 싶습니다. 예상 출력:

A T
A T
A T
C F
C F

어쩌면 awk그게 가능할까? 도움을 주셔서 미리 감사드립니다!

답변1

한 가지 방법은 다음과 같습니다 awk.

awk 'NR==FNR{if (x[$1]++){if ($2!=t){z[$1]++}} else {t=$2};
next}!($1 in z)' infile infile

이 프로세스는 파일을 두 번 처리합니다. 첫 번째 패스에서는 첫 번째 필드가 동일한 값일 때 두 번째 필드의 값이 다른지 확인합니다. 그렇다면 $1배열 인덱스로 사용되며, 두 번째 패스에서는 다음 경우에만 배치를 인쇄합니다. 첫 번째 필드는 해당 필드의 인덱스가 아닙니다. 또는 다음 과 함께
사용해도 괜찮다면 :sortawk

sort -u infile | awk 'NR==FNR{seen[$1]++;next}seen[$1]==1' - infile

sort -u파일에서 중복된 줄을 제거하고 결과를 파이프하여 awk첫 번째 필드의 발생 횟수를 계산한 다음 전체 파일을 다시 처리하고 개수가 이면 줄을 인쇄합니다 1.

답변2

sed -e '
   # this is a do-while loop which collects lines till the time the first
   # field remains the same. We break out of the loop when we see
   # a line whose 1st field != prev lines 1st field **OR** we hit the eof.
  :a
     $bb
     N
  /^\(\S\+\) .\(\n\1 .\)*$/ba

  :b

  # all equal
  # **Action:** Print and quit

  /^\(\S\+ .\)\(\n\1\)*$/q


  # all same 1st fld, but lines unequal, otw would have matched above
  # **Action:** Drop the whole block as its uninteresting

  /^\(\S\+\) .\(\n\1 .\)*$/d


  # all equal, and trailing line part of next line
  # **Action:** Display upto the last newline and restart 
  # with the trailing portion

  /^\(\(\S\+ .\)\(\n\2\)*\)\n[^\n]*$/{
     h
     s//\1/p   
     g
  }


  # of same 1st fld but some lines unequal, and trailing portion has
  # next line
  # **Action:** strip till the last newline, and restart over with the
  # trailing part

  s/.*\(\n\)/\1/
  D
' yourfile

이것은 "Sed"가 다루는 매우 흥미로운 문제입니다. 그러나 제가 찾은 것은 더 나은 것입니다. 아니면 OT가 SE에서 제공하는 더 큰 입력 세트라고 해야 할까요? 내 제안은 실제 크기와 종류의 테스트 사례를 http:/pastebin 사이트에 넣을 수 있다는 것입니다. 이는 이런 종류의 작업에 매우 유용할 것입니다.

답변3

접근 권한이 있는 경우GNU 데이터 혼합, 다음과 같이 데이터를 축소할 수 있습니다.

datamash -W groupby 1 countunique 2 collapse 2 < file 
A   1   T,T,T
B   2   T,T,F
C   1   F,F
D   2   F,T,F

awk이를 통해 다음 과 같은 후처리가 쉬워집니다 .

datamash -W groupby 1 countunique 2 collapse 2 < file | 
  awk '$2==1 {n = split($3,a,","); for (i=1;i<=n;i++) print $1, a[i]}'
A T
A T
A T
C F
C F

답변4

sed '
    /\n/D
    :1
    $! {
        N
        /^\(\S\+\s\).*\n\1[^\n]\+$/ b1
    }
    /^\([^\n]\+\n\)\(\1\)\+[^\n]\+$/! D
    h
    s/\n[^\n]\+$//p
    g
    s/.*\n/\n/
    D
    ' file

관련 정보