[unix] 정확한 수의 구분자를 포함하는 행만 유지하십시오.

10 개의 필드가 쉼표로 구분 된 거대한 csv 파일이 있습니다. 불행히도 일부 행의 형식이 잘못되어 정확히 10 개의 쉼표를 포함하지 않습니다 (파일을 R로 읽으려고 할 때 문제가 발생합니다). 정확히 10 개의 쉼표가 포함 된 행만 필터링하려면 어떻게해야합니까?



답변

다른 POSIX 것 :

awk -F , 'NF == 11' <file

행에 10 개의 쉼표가 있으면이 행에 11 개의 필드가 있습니다. 그래서 우리는 간단하게 awk사용 ,필드 구분 기호로 사용합니다. 필드 수가 11 인 경우 조건 NF == 11은 true이고 awk기본 조치를 수행합니다 print $0.


답변

사용 egrep(또는 grep -EPOSIX) :

egrep "^([^,]*,){10}[^,]*$" file.csv

이것은 10 개의 쉼표를 포함하지 않는 모든 것을 걸러냅니다 : ^시작과 $끝 의 전체 줄과 일치 하며, {10}” ‘,’을 제외한 모든 문자 수 뒤에 단일 ‘,'”순서로 정확히 10 개의 반복 ( )을 포함합니다. ( ([^,]*,)) 다음에 ‘,'( [^,]*)를 제외한 모든 문자가 다시 나옵니다 .

-x매개 변수를 사용 하여 앵커를 삭제할 수도 있습니다 .

grep -xE "([^,]*,){10}[^,]*" file.csv

이것은 cuonglmawk솔루션 보다 덜 효율적입니다 . 후자는 일반적으로 약 10 개의 쉼표가있는 줄의 경우 시스템에서 6 배 빠릅니다. 줄이 길면 속도가 크게 느려집니다.


답변

가장 간단한 grep코드 :

grep -xE '([^,]*,){10}[^,]*'

설명:

-x패턴이 일부가 아닌 전체 라인 과 일치해야 합니다. 쉼표가 10 개 이상인 행을 일치시키지 않도록하는 것이 중요합니다.

-E “확장 정규식”을 의미하므로 정규식에서 백 슬래시가 줄어 듭니다.

괄호는 그룹화에 사용되며, {10}이후에는 패러티 언 내의 패턴 행에 정확히 10 개의 일치 항목이 있어야 함을 의미합니다.

[^,]캐릭터는 클래스에 대한 인스턴스입니다 [c-f]A는 모든 단일 문자와 일치합니다 c하는 d, e또는를 f하고, [^A-Z]대문자 문자가 아닌 모든 문자를 것입니다. 따라서 [^,]쉼표를 제외한 모든 단일 문자와 일치합니다.

*문자 클래스 수단 후 “제로 또는 이들의 더.”

따라서 정규 표현식 부분 ([^,]*,)은 “쉼표를 여러 번 (0 번 포함) 제외하고 쉼표를 제외한 모든 문자”를 의미 {10}하며 이들 중 10 개를 지정합니다. 그런 다음 [^,]*나머지 비 쉼표 문자를 줄 끝과 일치시킵니다.


답변

sed -ne's/,//11;t' -e's/,/&/10p' <in >out

먼저 11 개 이상의 쉼표가있는 행을 분기 한 다음 10 개의 쉼표와 일치하는 항목 만 인쇄합니다.

분명히 나는 ​​전에 이것에 대답했다 … 여기 에 정확히 네 가지 패턴의 발생을 찾는 질문의 표절이 있습니다.

명령에을 추가하여 [num]sed s///ubstitution 명령으로 패턴 발생을 대상으로 지정할 수 있습니다 [num]. 때를 t추정 성공적인 교체 및 대상 지정하지 않은 :라벨의 t스크립트 중 추정 지점을. 즉 s///5, 쉼표 이상을 테스트 한 다음 남아있는 내용을 인쇄하기 만하면됩니다.

또는 적어도 최대 4를 초과하는 행을 처리합니다. 최소 요구 사항도 있습니다. 운 좋게도 그것은 간단합니다.

sed -ne 's|,||5;t' -e 's||,|4p'

,줄 에서 네 번째 항목을 그 자체로 바꾸고 찢김 플래그를 ubstitution 플래그 ps///붙입니다. ,5 번 이상 일치하는 행 은 이미 정리되었으므로 4 개의 ,일치 항목을 포함 하는 행은 4 개만 포함 합니다 .


답변

약간의 짧은 던지기 python:

#!/usr/bin/env python2
with open('file.csv') as f:
    print '\n'.join(line for line in f if line.count(',') == 10)

이것은 각 줄을 읽고 줄의 쉼표 수가 10과 같은지 line.count(',') == 10확인하여 줄이면 인쇄합니다.


답변

그리고 여기 Perl 방식이 있습니다 :

perl -F, -ane 'print if $#F==10'

-n원인 perl에 의해 주어진 스크립트 선으로 입력 파일 라인을 읽기 및 실행하기 위해 -e각 행을. -a자동 분할에 권선은 각 입력 라인에 의해 표시된 값에 분할한다 -F(여기서, 쉼표) 어레이로 저장 @F.

$#F(혹은 더 일반적으로 $#array) 배열의 최상위 인덱스이다 @F. 배열은에서 시작하므로 011 개의 필드가있는 행은의 @F입니다 10. 따라서 스크립트는 정확히 11 개의 필드가 있으면 행을 인쇄합니다.


답변

필드에 쉼표 나 줄 바꿈이 포함될 수 있으면 코드가 csv 를 이해해야 합니다. 예 (세 열) :

$ cat filter.csv
a,b,c
d,"e,f",g
1,2,3,4
one,two,"three
...continued"

$ cat filter.csv | python3 -c 'import sys, csv
> csv.writer(sys.stdout).writerows(
> row for row in csv.reader(sys.stdin) if len(row) == 3)
> '
a,b,c
d,"e,f",g
one,two,"three
...continued"

지금까지 대부분의 솔루션이 두 번째 및 네 번째 행을 삭제한다고 가정합니다.