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


9

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


1
귀하의 질문과 연결된 질문은 같은 질문 이 아닙니다 . 특정 수의 일치만으로 줄을 처리하는 방법을 묻는 반면,이 질문에는 최소 일치 수가 필요합니다. 실제로는 질문에 대한 답변이 더 쉽다는 것입니다.이 질문에는 해당하는 내용보다 한 줄을 더 스캔하거나 (적어도 sed여기에서하는 것처럼) 한 번 더 검색 할 필요가 없습니다. 이것을 닫지 말아야합니다.
mikeserv

1
실제로 가까이 찾고, 아스 커가 않습니다 싶지 보다 많거나 적은 경기. 그 질문에는 새로운 제목이 필요합니다. 그러나 grep대답은 두 질문 모두에 대한 수용 가능한 대답이 아닙니다 ...
mikeserv

답변:


21

다른 POSIX 것 :

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

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


5
그것이 실제로이 질문에 대해 가장 먼저 생각한 것입니다. 나는 그것이 과잉이라고 생각했지만 코드를 보면 ... 더 명확합니다. 다른 사람을 위해 : -F필드 구분 기호를 설정하고 NF주어진 행의 필드 수를 나타냅니다. {statement}조건에 코드 블록 이 추가 되지 않으므로 NF == 11기본 조치는 행을 인쇄하는 것입니다. (@cuonglm, 원하는 경우이 설명을 자유롭게 포함하십시오.)
Wildcard

4
+1 : 매우 우아하고 읽기 쉬운 솔루션으로 매우 일반적입니다. 예를 들어awk -F , 'NF != 11' <file
Miroslav Sabo

@gardenhead : OP가 그의 의견에서 말한 것처럼 쉽게 얻을 수 있습니다. 때로는 모바일에서 답변을하기 때문에 자세한 설명을 추가하기가 어렵습니다.
cuonglm

1
@ mikeserv : 아니요, 혼란스럽게하면 죄송합니다. 영어가 잘못되었습니다. 1-9 개의 쉼표로 11 개의 필드를 가질 수 없습니다.
cuonglm

1
@OlivierDulac :로 시작 -하거나 이름이 지정된 파일로부터 보호합니다 -.
cuonglm

8

사용 egrep(또는 grep -EPOSIX) :

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

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

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

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

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


5

가장 간단한 grep코드 :

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

설명:

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

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

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

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

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

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


5
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 개만 포함 합니다 .


1
@cuonglm-처음에 실제로 가지고 있었지만 사람들은 항상 더 읽을 수있는 코드를 작성해야한다고 말합니다. 내가 읽을 수없는 것으로 다른 사람들이 논쟁하는 내용을 읽을 수 있기 때문에 무엇을 보관하고 무엇을 떨어 뜨릴 지 잘 모르겠습니다 ...? 두 번째 쉼표를 넣습니다.
mikeserv

@cuonglm-당신은 나를 조롱 할 수 있습니다-그것은 내 감정을 해치지 않을 것입니다. 농담을 할 수 있습니다. 당신이 나를 조롱했다면 그것은 조금 재미있었습니다. 그것의 ok-나는 확실하지 않았고 알고 싶었다. 제 생각에는 사람들은 스스로 웃을 수 있어야합니다. 어쨌든, 나는 아직도 그것을 얻지 못한다!
mikeserv

하하, 그것은 매우 긍정적 인 생각입니다. 어쨌든, 당신과 채팅하는 것은 매우 재미 있고 때로는 내 두뇌에 스트레스를 줍니다.
cuonglm

그것은에 있다는 흥미로운 이 대답 내가 바꿀 경우 s/hello/world/2s//world/2, GNU가 잘 작동을 나오지. sed가보에서 두 개로 /usr/5bin/posix/sedsegfault를 높이고 /usr/5bin/sed무한 루프로 들어갑니다.
cuonglm

@mikeserv을 참조에 대한 우리의 이전 논의 sed하고awk 이 대답 같은 -I (주석)과 그것을 upvoted하지만, 허용의 번역 통지 awk대답은 "11 개 필드 라인을 인쇄"이 번역 sed대답은 " 11 번째 쉼표를 제거하려고합니다. 실패하면 다음 줄로 건너 뛰십시오. 10 번째 쉼표를 다른 것으로 바꾸려고 시도합니다. 성공하면 행을 인쇄하십시오. " awk대답은 컴퓨터의 지시에 당신이 영어를 표현하는 것이 바로 방법을 제공합니다. ( awk필드 기반 데이터에 적합합니다.)
Wildcard

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확인하여 줄이면 인쇄합니다.


2

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

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

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

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


print if @F==11스칼라 컨텍스트에서 배열로 요소 수를 반환 할 수도 있습니다 .
Sobrique

1

필드에 쉼표 나 줄 바꿈이 포함될 수 있으면 코드가 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"

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.