내 파일에는 여러 열이 포함되어 있으며 첫 번째 열은 ID에 해당합니다. 전체 파일에서 ID가 한 번만 나타나는 경우(첫 번째 열) 행을 삭제하고 싶습니다. ID가 여러 번 나타나면 해당 줄을 파일에 유지하고 싶습니다. ID는 A로 시작하는 문자(때로는 숫자)로 구성됩니다(다른 모든 문자/숫자는 무작위 순서입니다). 예를 들어:A2SGWS7CUGU8GB
만약 내가 가지고 있다면:
# id #column 2 ...
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
ADE8GST9URWPOS
ABXLMWJCQFGVXV
A2SGWS7CUGU8GB
ADE8GST9URWPOS
및 가 포함된 줄은 ABXLMWJCQFGVXV
한 번만 나타나므로 삭제하고 싶습니다 . 어떻게 해야 하나요?
답변1
먼저, 유지하려는 모든 중복 ID가 반환됩니다.
$ awk '{ print $1 }' <file | sort | uniq -d
A2SGWS7CUGU8GB
를 사용하여 첫 번째 공백으로 구분된 필드(ID)를 추출하여 이를 수행합니다 awk
. 그런 다음 이를 정렬하여 uniq -d
중복된 ID만 출력하는 데 사용됩니다.
그런 다음 이러한(이 경우 단일) ID를 사용하여 원본 파일에서 해당 줄을 추출할 수 있으며, 먼저 다음을 사용하여 정렬해야 합니다 join
.
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file )
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
쉘이 <(...)
임시 파일을 사용한 프로세스 교체를 지원하지 않는 경우 임시 파일을 사용하여 두 단계로 이를 수행할 수 있습니다.
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
사용오직 awk
, 이는 다음을 통해 수행할 수 있습니다.
$ awk 'NR == FNR { count[$1]++; next } count[$1] > 1' file file
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
코드가 파일을 두 번 읽기 때문에 명령줄에서 파일이 두 번 언급됩니다 awk
.
처음에는 연관 배열이 count
각 ID의 발생 횟수로 채워지고, 두 번째에는 ID가 여러 번 발생하는 각 행이 출력됩니다.
위 두 방법의 차이점은 awk
마지막 명령이 원본 데이터의 순서를 유지하지만 고유 ID 수에 비례하여 메모리를 소비한다는 것입니다. 첫 번째 접근 방식은 정렬된 결과를 생성하므로 더 적합할 수 있습니다.매우 크다데이터.
헤더 행을 유지하려면 명령을 약간 수정해야 합니다.
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file ) | cat <(head -1 file) -
또는
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted > file.noheader
$ head -1 file | cat - file.noheader
또는
$ awk 'NR == 1 ; NR == FNR { count[$1]++; next } count[$1] > 1' file file
답변2
awk '
!B {a[$1]++}
B && a[$1] > 1
' B=0 file B=1 file
첫 번째 필드(=ID)를 가져와 정렬한 다음 ID를 통합하고 중복된 항목만 유지합니다. 이를 xargs에 전달하고 각 ID를 기반으로 egrep ERE 정규식을 만듭니다.
< file \
cut -d" " -f1 \
| sort | uniq -d \
| xargs -I{} echo ^{}\\s \
| grep -Ef - file \
;
perl
slurp 파일 옵션을 사용 -0777
하고 레코드를 통해 정규식을 실행하면 각 줄의 시작 부분에서 ^
더 아래에 있는 첫 번째 필드(=ID)를 볼 수 있거나 ID가 이전에 발견된 경우 현재 줄을 인쇄합니다.
perl -0777ne '
() = m/(?msx)
^
(?<line>
(?<ID> A\w+)
\h.*?\n
)
(?=
(?:.*?\n)?
(?<lukahead> \g{ID}|$)
)
(?{ my %seen;
my($id_visible_ahead, $id_already_seen) =
map { $_ > 0 }
length($+{lukahead}), $seen{$+{ID}};
print($+{line}),$seen{$+{ID}}++
if $id_visible_ahead || $id_already_seen;
})
/g;
' file
산출:
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB