a.csv
, b.csv
및 이라는 세 개의 파일이 있습니다 c.csv
.
a.csv
내용이 있습니다
1234567,11111111111111111111111111111111111111111111111111
b.csv
비슷한 내용이 있어요
1234567845610111211111111111111111111111111
c.csv
내용이 있습니다
111111,22222222,3333333,,,44444444444444444444
위에서 언급한 세 개의 파일 중 a.csv
두 개의 열이 있는 파일에는 null 값이 포함되어서는 안 되며 나머지 파일( b.csv
및 )은 및 파일이 있는 다른 텍스트 파일 예제 c.csv
에 로드되어야 한다는 의미로만 이것이 필요합니다.List.txt
b.csv
c.csv
,
쉼표() 없이 파일을 삭제하기 위해 다음 명령을 시도했지만 작동하지 않는 것도 b.csv
고려해야 합니다.c.csv
grep -v "," *.csv |cut -d ":" -f1
제안한 대로 다음 명령을 시도했는데 두 개의 값 열이 있는 파일이 표시됩니다.
awk -F"," 'NF==2 {print FILENAME}' *.csv
하지만 유효하지 않은 파일을 다른 파일에 써야 할 경우 몇 가지 제안 사항을 알려주십시오.
제안된 대로 다음을 시도했지만 성공하지 못했습니다.
ls | grep -v $(awk -F"," 'NF==2 {print FILENAME}') *.csv|sort -u
나도 한번 해보라고 권유받았는데
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if(!ok)print FILENAME}' *.csv
그러나 이로 인해 다음과 같은 오류가 발생합니다.
awk: A statement occurred that is not valid.
The input line number is 1. The file is <Filename>
The source line number is 1.
두 번째 필드 값은 길이가 250자이고 a.csv
, b.csv
... 와 같은 n개 값이 있습니다.
답변1
내가 올바르게 이해했다면 다음 조건 중 하나라도 만족하는 줄이 포함된 파일을 삭제하고 싶을 것입니다.
- 필드 1이 비어 있습니다.
!$1
- 필드 2가 비어 있습니다.
!$2
- 2개의 필드가 없습니다.
NF!=2
그 다음에
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (ok) print FILENAME}' *.csv
ok=1
플래그를 설정한 다음 위의 조건 중 하나가 충족될 때까지 각 줄을 반복하고, "잘못된" 줄이 발견되면 파일을 무효화 ok=0
하고 더 이상 줄을 구문 분석하지 않고 파일 끝으로 점프합니다 nextfile
.
각 파일의 끝에서 0이 아닌 경우에만 ENDFILE
인쇄됩니다 .FILENAME
if (ok)
따라서 일치를 무효화하려면 마지막 테스트를 반전하여 if (!ok)
인쇄 하면 됩니다.
awk -F',' 'BEGINFILE{ok=1}!$1||!$2||NF!=2{ok=0; nextfile}ENDFILE{if (!ok) print FILENAME}' *.csv
편집하다
출력에서 오류를 재현할 수 없습니다 gawk
(파일 이름을 xxx.file로 리디렉션하는 것을 포함하여 아래 참조).
bash --version
GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)
awk --version
GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
tail -n +1 *.csv;
awk -F',' 'BEGINFILE{ok=1}
!$1||!$2||NF!=2{ok=0; nextfile}
ENDFILE{gzout=(ok)?"ok":"banjaxed"; print FILENAME > gzout".files"}' *.csv ;
tail -n +1 *.files
==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111
==> b.csv <==
1234567845610111211111111111111111111111111
==> c.csv <==
111111,22222222,3333333,,,44444444444444444444
==> banjaxed.files <==
b.csv
c.csv
==> ok.files <==
a.csv
단일 필드 길이 제한(1024)문제가 되어서는 안 된다awk
3,000자 레코드 제한을 위반 하지 않는 한 , 이 경우 awk
둘 다 sed
작업에 적합한 도구가 아닌 것 같습니다.
답변2
대안으로, grep
어느 쪽도 사용할 수 없으며 다음이 있다고 가정하고 사용 하십시오 sed
.grep
수천당 파일 수수천grep
줄이 상당히 길기 때문에 줄 전체를 핑하는 대신 각 줄의 첫 번째 줄만 확인하고 싶을 것입니다 .
모든 첫 번째 줄(파일 이름 포함)을 가져와서 파일에 넣습니다.
head -n1 *.csv > list
각 항목에는 아래와 같이 컨텍스트(파일 이름) 줄, 첫 번째 줄, 그 뒤에 빈 줄이 있습니다.
==> a.csv <==
1234567,11111111111111111111111111111111111111111111111111
==> b.csv <==
1234567845610111211111111111111111111111111
선에 맞는 패턴이 이라는 것을 알고 있으므로 ^[0-9.]+,[0-9.]+$
다음을 수행할 수 있습니다.
grep -E -B1 "^[0-9]+,[0-9]+$" list | grep -oP "(?<= )[^, <]+" > ok.list
첫 번째는 이전 컨텍스트 줄 grep
(일치하는 파일 이름 포함)에서 일치 항목을 추출하고, 두 번째는 파일 이름을 추출하여 원하는 파일에 덤프합니다.list
-B1
ok.list
ok.list
마지막으로 다음을 사용하여 필터링 할 수 있습니다 .
ls *.csv | grep -Fvxf ok.list > banjaxed.list
고정 문자열(정규식 아님) "-F"의 파일을 사용하여 파일을 grep
필터링할 수 있고, 완전 일치는 파일을 일치시킬 패턴 목록으로 사용하며, 물론 역방향 일치는 필터링된 파일 열을 Out로 리디렉션하게 됩니다.ok.list
ls
-x
-f
-v
banjaxed.list
그것이 적어도 돈의 가치가 없다면, 나는 장난감을 치울 것입니다.