zsh에서 csv 파일을 한 줄씩 구문 분석하고 쉼표 없이 배열에 저장하고 싶습니다. zsh에서 행을 배열로 가져온 후 다음 행을 가져올 수 있습니까?
문제는 대용량 csv 파일을 사용하고 있는데 모든 파일을 빠르게 가져올 수 없다는 것입니다. 다음 코드를 사용해 보았습니다.
arr_csv=()
while IFS= read -r line
do
arr_csv+=("$line")
done < import.csv
그런데 파일이 크기 때문에 한 행을 읽고 저장(또는 한 행에 액세스)하고 싶습니다.
다음과 같이 코드를 수정할 수 있다는 것을 알고 있습니다.
arr_csv=()
while IFS= read -r line
do
arr_csv=("$line")
# some modifications
done < import.csv
하지만 파일을 반복하고 싶다면 csv 파일의 행에 해당하는 인덱스를 사용할 수 있으면 더 쉬울 것입니다. 또한 이 방법은 줄을 구분하는 쉼표를 제거하지 않습니다.
답변1
제가 말하려는 것은 셸이 아닌 perl
/...here 와 같은 CSV 지원이 포함된 올바른 프로그래밍 언어를 사용해야 한다는 것입니다.python
그러나 zsh
개별 셀에서 줄 바꿈과 캐리지 리턴을 사용해야 하고 제거하는 데 신경 쓰지 않는다면 csvkit을 사용하여 csv를 더 쉽게 처리 할 수 csvformat
있는 형식으로 다시 포맷 할 수 있습니다.zsh
read
< file.csv csvformat -SU3 -P'\' |
while IFS=, read -A array; do
typeset array # or anything with $array
done
예를 들어 다음과 같은 입력의 경우:
"foo bar ", "x,y", "blah""blah","new
line"
1,,2,"\\"
csv와 관련된 일반적인 잠재적 함정의 예는 다음과 같습니다.
array=( 'foo bar ' x,y 'blah"blah' newline )
array=( 1 '' 2 '\\' )
누락된 경우 -r
이스케이프 문자로 read
인식됩니다 . \
불행하게도 로 이스케이프되었지만 csvformat
개행 문자를 이스케이프하는 것이 아니라 줄 연속으로 해석됩니다.<newline>
\<newline>
read
입력에 전혀 나타나지 않는 두 문자를 알고 있는 경우 이를 각각 필드 구분 기호와 레코드 구분 기호로 사용할 수 있습니다. 예를 들어 ASCII일 수 있습니다.기록 구분 기호그리고단위 구분 기호여기에는 제어 문자가 적절한 것 같습니다.
us=$'\x1f' rs=$'\x1e'
< file.csv csvformat -SU3 -D$us -M$rs -Q$rs |
while IFS=$us read -rd$rs -A array; do
something with $array
done
이번에는 동일한 입력이 주어지면 다음과 같습니다.
array=( 'foo bar ' x,y 'blah"blah' $'new\nline' )
array=( 1 '' 2 '\\' )