这是我的 CSV 文件:
Number;Reference;EANNumber;Manufacturer;Price_B2B;Price_B2B_Dis;Price_B2B_DisPer;Price_B2B_DisAmount;Price_B2C_exVAT;Price_B2C_inVAT
2330113;BP3141;1,31304E+11;APC;13;13;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1402141;A51U;8,84333E+11;HP;2;2;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1450121;LC125XLC;4,34444E+12;Brother;11,4;11,4;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5431414;YEG-00431;343434315;Msoft;11,1;11,1;0;0;31,45;41,31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5533314;QQC-08323;8,85341E+11;Microsoft;522,23;522,23;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3140025;30MB0SY0-M0EAY0;1,4123E+12;Asus;11,33;11,33;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1452531;R18-05435;3,33334E+12;Microsoft;24;24;0;0;1,8;1,33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4480158;M28-00002;;Meyss;54,22;54,22;0;0;11,13;31,13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2310152;AC2T0E;;HP;52;52;0;0;0;0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
我想通过 bash 脚本执行以下公式:
=当(I2=0;E2*1,2;I2)
价格应显示在 x 列中
你能用 awk 或 gawk 做到这一点吗?我已经尝试过,但无法进一步。
我想读取 CSV 文件并在 CSV 文件中运行计算。
答案1
我假设您想要一个用字段x
中的值调用的新字段Price_B2C_exVAT
,除非该值为零,在这种情况下您需要Price_B2B
字段中值的 1.2 倍。
以下代码将输入读取为带有标题的“不规则”CSV 文件(“不规则”是因为记录中存在不同数量的字段),并首先使用remove-empty-columns
子命令删除空列。然后,它x
使用给定的公式在每个记录中创建新字段。
我们可以计算新字段的值磨坊主( mlr
) 像这样:
mlr --csv --fs ';' --ragged \
remove-empty-columns then \
put '$x = $Price_B2C_exVAT; $x == 0 { $x = 1.2*$Price_B2B }' file.csv
如果您的浮点值用作.
小数点而不是,
,那么这会很有效。相反,我们Price_B2B
只需将逗号替换为点即可将值从字符串转换为浮点值:
mlr --csv --fs ';' --ragged \
remove-empty-columns then \
put '$x = $Price_B2C_exVAT; $x == 0 { $x = 1.2*float(ssub(string($Price_B2B),",",".")) }' file.csv
要将浮点值转换为使用逗号代替点的字符串,我们执行与x
之前相反的操作Price_B2B
:
mlr --csv --fs ';' --ragged \
remove-empty-columns then \
put '
$x = $Price_B2C_exVAT;
$x == 0 {
$x = 1.2*float(ssub(string($Price_B2B), ",", "."));
$x = ssub(string($x), ".", ",");
}' file.csv
或者,put -S
阻止 Miller 推断字段中数据的类型并将其保留为字符串(这消除了Price_B2B
在其为零的情况下显式转换为字符串的需要):
mlr --csv --fs ';' --ragged \
remove-empty-columns then \
put -S '
$x = $Price_B2C_exVAT;
$x == "0" {
$x = 1.2*float(ssub($Price_B2B, ",", "."));
$x = ssub(string($x), ".", ",");
}' file.csv
结果,使用问题中的示例(该x
字段被添加到字段列表的末尾):
Number;Reference;EANNumber;Manufacturer;Price_B2B;Price_B2B_Dis;Price_B2B_DisPer;Price_B2B_DisAmount;Price_B2C_exVAT;Price_B2C_inVAT;x
2330113;BP3141;1,31304E+11;APC;13;13;0;0;0;0;15,600000
1402141;A51U;8,84333E+11;HP;2;2;0;0;0;0;2,400000
1450121;LC125XLC;4,34444E+12;Brother;11,4;11,4;0;0;0;0;13,680000
5431414;YEG-00431;343434315;Msoft;11,1;11,1;0;0;31,45;41,31;31,45
5533314;QQC-08323;8,85341E+11;Microsoft;522,23;522,23;0;0;0;0;626,676000
3140025;30MB0SY0-M0EAY0;1,4123E+12;Asus;11,33;11,33;0;0;0;0;13,596000
1452531;R18-05435;3,33334E+12;Microsoft;24;24;0;0;1,8;1,33;1,8
4480158;M28-00002;;Meyss;54,22;54,22;0;0;11,13;31,13;11,13
2310152;AC2T0E;;HP;52;52;0;0;0;0;62,400000
答案2
对于简单的 CSV,您应该能够摆脱awk
.在用作,
十进制基数字符的区域设置中:
POSIXLY_CORRECT=1 awk -F ';' -v OFS=';' '
{print $0, NR == 1 ? "x" : $9 ? $9 : $5 * 1.2}' < file.csv
将添加一个额外的字段:
- 在第一行 (
NR == 1
) 中,x
- 在其他线路上:
- 如果
$9
(第9个字段)不为0,$9
- 否则第 5个字段乘以 1.2。
- 如果
要更改浮点数的格式,CONVFMT
请像使用 和 一样设置变量(不影响整数)进行-v CONVFMT=%.2f
数值转换,例如在第二个 前面添加 0+ $9
,或者更好,因为它也会影响整数:
POSIXLY_CORRECT=1 awk -F ';' -v OFS=';' '
{print $0, NR == 1 ? "x" : sprintf("%.2f", $9 ? $9 : $5 * 1.2)}' < file.csv
用于POSIXLY_CORRECT=1
GNU,awk
如果没有它,GNU 就不会遵守语言环境的十进制基数。