printf "%.3f" ${带换行符的变量} - 错误 \n

printf "%.3f" ${带换行符的变量} - 错误 \n

喜欢这里我有一个文件.csv引号中的数字:

"0.2"
"0.3339"
"0.111111"

要四舍五入数字(小数点后三位),此解决方案效果很好:

printf "%.03f\n" $(sed 's/\"//g' file.csv)

但现在我想存储sed 's/\"//g' file.csv为变量

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" ${var_sed}

不起作用。输出是

zsh: bad math expression: operator expected at `0.3339\n0.1...'
0.000

所以问题是var_sed传递\nprintf "%.03f\n".

我知道的唯一解决方案是:

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" $(echo ${var_sed})
  1. 也许有更干净的方法。
  2. 我还想放入printf "%.03f\n"一个这样的函数:
printf_function () { printf "%.03f\n" $1;}

但这不起作用:

printf_function () { printf "%.03f\n" $1;};
var_sed=$(sed 's/\"//g' file.csv);
printf_function ${var_sed}

printf_function $(echo ${var_sed})不起作用。

____________________________________________________________

为什么我尝试将文件保存在变量中? ____________________________________________________________

事实是,我实际上想将sed命令放入函数中。很抱歉,我将其作为变量来(尝试)简化问题。

我的脚本是

sed_01 () { sed 's/\"$// ; s/^\"// ; s/something_else//g' $1;};
printf_03 () { printf "%.03f\n" $1;};
printf_03 "$(sed_01 file.csv)"

正如下面的评论中提到的,它在 bash 中工作。

输出:

"0.200"
"0.334"
"0.111"

但在 zsh 中输出:是:

printf_03: bad math expression: operator expected at `0.3339\n0.1...'
0.000

答案1

printf "%.03f\n" $(sed 's/\"//g' file.csv)

var_sed=$(sed 's/\"//g' file.csv);
printf "%.03f\n" ${var_sed}

这依赖于分词来将数字printf作为单独的参数。问题是,zsh 已经放弃了自动分词作为过去的愚蠢残余,并且不会为变量扩展执行此操作。但无论出于何种原因,它确实是为了命令替换而这样做的。

从命令替换分配给常规标量变量时也没有拆分,因此输出中的换行符sed保存在变量中。

这就是为什么您的代码可以使用命令替换,但不能使用中间变量。

如果您确实需要首先加载变量中的值(并且您不只是为了打印),请考虑将它们存储在数组中(zsh):

lines=("${(f)$(sed 's/\"//g' file.csv)}")
printf "%.03f\n" $lines

在 Bash 中,你可以使用readarray/ mapfile

mapfile -t lines < <(sed 's/\"//g' file.csv)
printf "%.03f\n" "${lines[@]}"

或者,如果您想要主要适用于其中任何一个的东西,您将不得不再次依赖分词:

lines=( $(sed 's/\"//g' file.csv) )
printf "%.03f\n" "${lines[@]}"

请注意括号,它们使数组赋值,因此再次发生分词。(“主要”包括影响行为的修改的常见警告IFS,并且文件名通配也会发生。)


话又说回来,仅使用 AWK 可能会更容易完成类似的事情:

$ awk '{gsub(/"/, ""); printf "%.03f\n", $1}' file.csv
0.200
0.334
0.111

相关内容