读取 CSV 文件,无法打印出最终值的结尾双引号

读取 CSV 文件,无法打印出最终值的结尾双引号

我正在尝试将 .csv 文件的行(在 google 表格中创建并下载到我的本地计算机)转换为 javascript 对象。我能够正确输出所有字段,除了最后一个字段拒绝打印最后的双引号。此外,终端的输出放错了我的结尾“]”并将其放置在“comps”行的开头(而不是末尾)。为什么最后的双引号不能正确打印出来?

#! /usr/bin/env bash

list_file="input.csv"
destination_file="output.js"

IFS=","

while read field1 field2 field3 field4 field5 field6 field7 field8 field9 field10 field11 field12 field13 field14
do
    echo '"'${field8}'": { r: "'${field2}'", g: "'${field3}'", b: "'${field4}'", hex: "'${field5}'", code: "'${field1}'", 
    desc: "'${field9}'",
    comps: ["'${field10}'", "'${field11}'", "'${field12}'", "'${field13}'", "'${field14}'"]
    },' >> $destination_file
done < $list_file

echo "};" >> $destination_file

一行的输出如下所示:

"#288": { r: "x", g: "x", b: "x", hex: "x", code: "XXXX", 
    desc: "description here",
"], comps: ["#1", "#2", "#3", "#4", "#5
    },

在第三行,首先打印最后的双引号和结束括号。

此外,在测试每个单独的字段时使用:

echo '"' $field14 '"'

我仅对最后一个字段得到相同的输出(没有结束双引号)。然而,所有其他字段都按预期打印。

答案1

Shell 对于文本和数据处理来说是一种糟糕的语言。 Shell 的工作是协调其他程序的执行来完成工作(而且它很擅长),而不是完成工作本身。使用更适合文本(和 CSV)处理的语言。例如,perl:

$ cat csv-to-js.pl 
#!/usr/bin/perl

use strict;
use Text::CSV qw(csv);

my $fmt = <<__EOF__;
"%s": { r: "%s", g: "%s", b: "%s", hex: "%s", code: "%s",
    desc: "%s",
    comps: ["%s", "%s", "%s", "%s", "%s"],
    },
__EOF__

# default to reading stdin if no args are supplied
push @ARGV, '/dev/stdin' unless (@ARGV);

my $csv = Text::CSV->new();

foreach my $f (@ARGV) {
  open my $fh, "<", $f or die "$f: $!";
  while (my $row = $csv->getline($fh)) {
    printf $fmt, @$row[7,1..4,0,8,9..13]; # perl arrays start from 0, not 1
  };
  close $fh;
}

这使用了文本::CSV模块,不包含在核心perl中,需要单独安装。在 Debian 以及 Ubuntu 和 Mint 等衍生产品上,使用sudo apt-get install libtext-csv-perl.其他 Linux 发行版将有类似命名的软件包,否则使用cpan.

该脚本为 printf 创建格式字符串,打开命令行上列出的 CSV 文件,读取并解析每一行,然后使用 printf 打印它们。

顺便说一句,无论行仅以 LF (unix 文本文件)还是以 CR/LF (dos/windows 文本文件)结尾,该脚本都可以工作。

输入示例:

$ cat input.csv 
XXXX,x,x,x,x,6,7,"#288","description here","#1","#2","#3","#4","#5"
YYYY,x,x,x,x,6,7,"#289","another description here","#1","#2","#3","#4","#5"
ZZZZ,x,x,x,x,6,7,"#290","and another description here","#1","#2","#3","#4","#5"

样本运行:

$ ./csv-to-js.pl input.csv 
"#288": { r: "x", g: "x", b: "x", hex: "x", code: "XXXX",
    desc: "description here",
    comps: ["#1", "#2", "#3", "#4", "#5"],
    },
"#289": { r: "x", g: "x", b: "x", hex: "x", code: "YYYY",
    desc: "another description here",
    comps: ["#1", "#2", "#3", "#4", "#5"],
    },
"#290": { r: "x", g: "x", b: "x", hex: "x", code: "ZZZZ",
    desc: "and another description here",
    comps: ["#1", "#2", "#3", "#4", "#5"],
    },

答案2

感谢评论,我添加了这一行以删除以最后一个字段结尾的 CRLF 行以及按应打印的代码。

field14=$(echo $field14 | sed 's/\r//g')

相关内容