두 개의 .csv 파일이 있습니다. 첫 번째 파일에는 단어 목록이 있습니다. 두 번째 파일에는 두 개의 열이 있으며 첫 번째 열에는 첫 번째 파일의 항목과 일치하는 값이 포함됩니다. 첫 번째 파일을 한 줄씩 읽고 각 줄을 사용하여 두 번째 파일을 grep하고 싶습니다. 현재 코드 표시
- 행을 읽을 때
- 하다
- grep $line ./filetwo.csv
- <fileone.csv 완료
이 코드는 아무것도 생성하지 않습니다. $line을 파일을 읽어 할당되지 않은 변수로 바꾸면 완벽하게 작동합니다. 나는 수년 동안 이 문제를 연구해 왔지만 겉보기에 간단해 보이는 질문에 대한 답을 결코 찾지 못했습니다. .csv 파일을 읽어 할당된 변수가 직접 할당된 변수와 동일한 결과를 제공하지 않는 이유를 이해할 수 없습니다. zsh 쉘을 사용하고 있습니다.
답변1
CSV 파일은 Microsoft 세계에서 더 일반적이므로 다음을 찾을 수 있습니다.
- 로캘의 문자 집합이 아닌 UTF-16으로 인코딩되므로 변환이 필요합니다.
- 또는 UTF-8로 인코딩되지만 바이트 순서 표시가 있습니다.
- CRLF 줄 구분 기호가 있습니다.
- 마지막 줄은 분리되지 않습니다(따라서
read
false가 반환됩니다).
이것이 사실인지 확인할 수 있습니다 file yourfile.csv
.
그러면 다음과 같이 할 수 있습니다:
dos2unix < fileone.csv |
while IFS=, read -r first rest_if_any_ignored; do
dos2unix < filetwo.csv | grep -Fe "$first"
done
(정규식 일치(in ) -F
를 수행하는 기본값이 아닌 고정 문자열 검색에 유의하십시오 .) 그러나 이는 각 행에 대해 세 개의 명령을 실행하고 각 명령이 매번 처음부터 내용을 처리하기 때문에 상당히 비효율적입니다 .re
grep
fileone.csv
grep
filetwo.csv
$first
또한 첫 번째 열뿐만 아니라 의 모든 위치에서 문자열을 찾고 filetwo.csv
정확한 일치를 수행하지 않습니다. 예를 들어 $first
is 인 foo
경우 foobar,other
및 other,foobar
행이 보고됩니다. 이는 또한 CSV 참조를 처리하지 않습니다. 따라서 적절한 CSV 구문 분석 기능을 갖춘 언어를 사용하는 것이 좋습니다.
이러한 파일이 간단한 CSV, 즉 참조나 헤더가 없는 경우 다음 작업이 수행됩니다 join
.
preprocess() {
dos2unix -O -- "$@" | sort -t, -k1b,1
}
join -t, <(preprocess < fileone.csv) <(preprocess < filetwo.csv)
헤더와 가능한 따옴표(줄 바꿈이 포함된 데이터 포함)가 있는 실제 CSV의 mlr
경우 CSV 파서를 사용할 수 있습니다.그것의 join
동사.
foo
예를 들어 첫 번째 열이 in fileone.csv
및 bar
in 으로 호출되는 경우 filetwo.csv
:
mlr --csv join -j foo -r bar -f fileone.csv filetwo.csv
dos2unix
CRLF, 무제한 라인 및 BOM이 있는 UTF-8을 처리할 수 있지만 UTF-16은 처리할 수 없습니다. 먼저 UTF-8을 사용하거나 UTF- 8 로 변환해야 합니다 iconv
.
mlr
간단한 CSV 및 기타 여러 테이블 형식도 수행할 수 있습니다. 자세한 내용은 해당 설명서를 참조하세요.