filename.csv
我有一个包含以下内容的CSV 文件。
文件名.csv:
"Afghanistan","94.0","81.1"
"Bahamas","42.9","43.2"
"Bolivia (Plurinational State of)","86.7","31.9"
"Brazil","76.7","0.0"
我想计算两列(第 2 列 - 第 3 列)之间的差异,但得到的输出不正确。其他列中的所有数据都消失了,并且我从减法命令中得到了错误的输出。
我使用的命令:awk '{ print $2 - $3 }' filename.csv
我得到的输出:
0
0
0
0
预期输出文件:
"Afghanistan","94.0","81.1","12.9"
"Bahamas","42.9","43.2","-0.3"
"Bolivia (Plurinational State of)","86.7","31.9","54.8"
"Brazil","76.7","0.0","76.7"
任何帮助表示赞赏。谢谢。
答案1
awk 中的默认分隔符是空格,但 csv 使用引号和逗号,因此 awk 默认情况下会将 csv 文件视为一大列。
另外,您需要去掉引号才能识别数字。因此,您可以使用-F'","'
将分隔符更改为用逗号分隔的引用字符串,只要引用的字符串不只包含逗号,这就可以工作。
awk -F'","' '{ print $2 - $3 }' filename.csv
请注意,您必须引用 shell 的引号。
答案2
这有效:
$ awk 'BEGIN{FS=OFS="\""}{$7=",\""$4-$6"\""}1' filename.csv
输出:
"Afghanistan","94.0","81.1","12.9"
"Bahamas","42.9","43.2","-0.3"
"Bolivia (Plurinational State of)","86.7","31.9","54.8"
"Brazil","76.7","0.0","76.7"
作为旁白,如果数字字段没有被引用,它会简单得多:awk -F, '{$4=$2-$3}1' filename.csv
。
答案3
使用乐(以前称为 Perl_6)
raku -MText::CSV -e 'my @a = csv(in => "/Path/To/File"); \
my @b = @a.map(*.[1]) Z- @a.map(*.[2]); \
.put for @a Z @b;'
#OR
raku -MText::CSV -e 'my @a = csv(in => "/Path/To/File"); \
.put for @a Z (@a.map(*.[1]) Z- @a.map(*.[2]));'
输入示例:
"Afghanistan","94.0","81.1"
"Bahamas","42.9","43.2"
"Bolivia (Plurinational State of)","86.7","31.9"
"Brazil","76.7","0.0"
示例输出:
Afghanistan 94.0 81.1 12.9
Bahamas 42.9 43.2 -0.3
Bolivia (Plurinational State of) 86.7 31.9 54.8
Brazil 76.7 0.0 76.7
虽然我确信您可以自行解析 csv(对于小型项目),但在某些时候使用 CSV 解析器可能是有意义的(处理嵌入的引号、嵌入的换行符、检测/更改逗号/非逗号列分隔符、修剪空格等)。
bash
您可能会惊讶地发现,在 Raku 编程语言的命令行中调用 CSV 解析器是多么容易。首先使用(module) 命令行标志加载Text::CSV
模块,这将为您提供.然后告诉 Raku 期望代码后面带有命令行标志。-M
-MText::CSV
-e
为了解释第一个示例,@a
我们声明了一个数组my
并采用 csv 输入。@b
声明一个数组my
,它采用(零索引)第 1 列和第 2 列之间的差异。这种差异是通过Z
zip 元操作符附加减号运算符来实现的,以使Z-
。最后,Z
使用 zip 元操作符输出原始@a
csv,并按列逐行压缩@b
。
https://github.com/Tux/CSV/blob/master/doc/Text-CSV.pdf(点击下载链接)
https://docs.raku.org/language/operators#index-entry-Z_(zip_metaoperator)
https://raku.org
答案4
使用磨坊主( mlr
) 读取无标头 CSV 文件,通过计算第二个和第三个字段之间的差异来创建新的第四个字段,根据标准格式说明符格式化生成的浮点值%g
,并输出带引号的 CSV:
$ mlr --csv -N --quote-all put '$4 = fmtnum($2 - $3, "%g")' file
"Afghanistan","94.0","81.1","12.9"
"Bahamas","42.9","43.2","-0.3"
"Bolivia (Plurinational State of)","86.7","31.9","54.8"
"Brazil","76.7","0.0","76.7"
请注意,%g
在 Miller 的后续版本中,格式似乎已被破坏,因此您可能需要使用类似的内容%.6g
。