10 개의 필드가 쉼표로 구분 된 거대한 csv 파일이 있습니다. 불행히도 일부 행의 형식이 잘못되어 정확히 10 개의 쉼표를 포함하지 않습니다 (파일을 R로 읽으려고 할 때 문제가 발생합니다). 정확히 10 개의 쉼표가 포함 된 행만 필터링하려면 어떻게해야합니까?
답변
다른 POSIX 것 :
awk -F , 'NF == 11' <file
행에 10 개의 쉼표가 있으면이 행에 11 개의 필드가 있습니다. 그래서 우리는 간단하게 awk
사용 ,
필드 구분 기호로 사용합니다. 필드 수가 11 인 경우 조건 NF == 11
은 true이고 awk
기본 조치를 수행합니다 print $0
.
답변
사용 egrep
(또는 grep -E
POSIX) :
egrep "^([^,]*,){10}[^,]*$" file.csv
이것은 10 개의 쉼표를 포함하지 않는 모든 것을 걸러냅니다 : ^
시작과 $
끝 의 전체 줄과 일치 하며, {10}
” ‘,’을 제외한 모든 문자 수 뒤에 단일 ‘,'”순서로 정확히 10 개의 반복 ( )을 포함합니다. ( ([^,]*,)
) 다음에 ‘,'( [^,]*
)를 제외한 모든 문자가 다시 나옵니다 .
-x
매개 변수를 사용 하여 앵커를 삭제할 수도 있습니다 .
grep -xE "([^,]*,){10}[^,]*" file.csv
이것은 cuonglm 의 awk
솔루션 보다 덜 효율적입니다 . 후자는 일반적으로 약 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]
seds///
ubstitution 명령으로 패턴 발생을 대상으로 지정할 수 있습니다[num]
. 때를t
추정 성공적인 교체 및 대상 지정하지 않은:
라벨의t
스크립트 중 추정 지점을. 즉s///5
, 쉼표 이상을 테스트 한 다음 남아있는 내용을 인쇄하기 만하면됩니다.또는 적어도 최대 4를 초과하는 행을 처리합니다. 최소 요구 사항도 있습니다. 운 좋게도 그것은 간단합니다.
sed -ne 's|,||5;t' -e 's||,|4p'
…
,
줄 에서 네 번째 항목을 그 자체로 바꾸고 찢김 플래그를 ubstitution 플래그p
에s///
붙입니다.,
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
. 배열은에서 시작하므로 0
11 개의 필드가있는 행은의 @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"
지금까지 대부분의 솔루션이 두 번째 및 네 번째 행을 삭제한다고 가정합니다.