bash에서 CSV를 TSV로 변환해야 합니다. 내가 찾은이것솔루션은 잘 작동하지만 아래와 같이 모든 데이터 세트에 대해서는 작동하지 않습니다.
예를 들면 다음과 같습니다 a.txt
.
a,"test, part2 ""the start""",b
sed
잘못된 형식:
[ nir ]$ cat a.txt | sed -E 's/("([^"]*)")?,/\2\t/g'
a "test Op. 15 ""the start" b
#^ tab....^ tab..................^ tab
여기에 문제가 있습니다: 누락 ,
, 추가 탭, 추가 따옴표.
참고로 파이썬 코드의 형식도 잘못되었습니다.
[ nir ]$ cat a.txt | csv2tsv.py
a "test, part2 ""the start""" b
#^ tab..........................^ tab
여기서 문제는 추가 따옴표입니다.
csv2tsv.py
예:
csv.writer(sys.stdout, dialect='excel-tab').writerows(csv.reader(sys.stdin))
실제 변환은 다음과 같아야 합니다.
a test, part2 "the start" b
#^ tab......................^ tab
이 문제를 해결하는 방법에 대한 피드백을 받고 싶습니다 bash
. 나는 인터넷에서 많은 솔루션을 보았지만 따옴표 안의 따옴표를 처리하지 못했습니다. :)
답변1
그리고 mlr
:
mlr -N --icsv --otsvlite cat < file.csv > file.tsv
또는:
mlr -N --c2t --quote-none cat < file.csv > file.tsv
그러나 csv 필드에 탭 문자가 포함되어 있으면 출력에서 이스케이프 처리되지 않으므로 추가 필드가 발생합니다.
GNU를 사용하면 sed
같은 일을 할 수 있습니다:
sed -E '
# append next line as long as there is not an even number
# of "s, to handle fields with newline. You can omit this line
# if the fields are guaranteed not to contain newlines:
:1; /^([^"]*"[^"]*")*[^"]*$/! {N;b1}
s/$/,/
s/(([^,"]*)|"((""|[^"])*)"),/\2\3\t/g
s/\t$//
s/""/"/g' < file.csv > file.tsv
입력은 현재 로케일의 유효한 텍스트로 간주됩니다. 먼저 현지화를 sed
비활성화 LC_ALL=C sed...
하고 입력을 바이너리로 처리하여 디코딩 문제를 방지합니다(속도가 문제가 되는 경우 속도가 빨라질 수 있음).
답변2
로드 가능한 CSV 모듈이 포함된 bash 5.1
BASH_LOADABLES_PATH=${BASH/\/bin\//\/lib\/}
enable -f csv csv
csv -a fields "$line"
new_line=$(IFS=$'\t'; echo "${fields[*]}")
declare -p line fields new_line
산출
declare -- line="a,\"test, part2 \"\"the start\"\"\",b"
declare -a fields=([0]="a" [1]="test, part2 \"the start\"" [2]="b")
declare -- new_line="a test, part2 \"the start\" b"
#.....................^ tab......................^ tab
탭이 포함된 필드가 있는 경우에는 아무런 효과가 없습니다.
파이프라인에서:
IFS=$'\t'
cat file |
while IFS= read -r line; do
csv -a fields "$line"
echo "${fields[*]}"
done |
tail
이것은 좀 더 관용적인 bash이지만
IFS=$'\t'
while IFS= read -r line; do
csv -a fields "$line"
echo "${fields[*]}"
done < file | tail