使用 bash 拆分字符串在 debian 服务器中不起作用



我想使用 " of " 拆分ins_data字符串并将 2 个数字分成 2 个变量。

我的代码是这样的。

#!/usr/bin/env bash
ins_data="3,998 of 5,903"
IFS=' of ' read -ra ins_data_arr <<< ${ins_data}
total_ins=${ins_data_arr[1]//,}
missed_ins=${ins_data_arr[0]//,}
echo $total_ins
echo $missed_ins

此代码在我的 mac 操作系统机器中工作正常。

但它在 Debian 服务器中不起作用。

$ ins_data="3,998 of 5,903"
$ IFS=' of ' read -ra ins_data_arr <<< ${ins_data}
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="5,903")'
$ IFS=' of ' read -ra ins_data_arr <<< "$ins_data"
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="5,903")'

起初我发现这种行为很混乱:那个空地从何而来?我认为任何 IFS 字符序列都会分隔字段。

对于 IFS 的默认值也是如此

这是 IFS 与分词相关的一种非常微妙的行为:

如果IFS的值不是默认值,则只要空格字符的值为IFS(IFS空格字符),则在单词的开头和结尾忽略空格字符序列spacetabnewlineIFS中任何不是空格IFS字符以及任何相邻IFS空格字符一起分隔字段。IFS空格字符的序列也被视为分隔符。

因此:零个或多个空格的序列和单个非空格的 IFS 字符分隔字段。

索引 1 处的空数组元素是 "o" 和 "f" 之间的空字符串。

该测试强化了这一说法:

$ IFS=' of ' read -ra ins_data_arr <<< "3,998 off 5,903"
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="" [3]="5,903")'
现在我们在"o"和"f"之间有一个空字段,在"f">

和"f"之间有一个空字段。

我认为这是 bash 版本 4 的新行为——OSX 上的默认 bash 是版本 3.something。行为改变的答案将在这里的某个地方:https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=bash-4.4


找到它:https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=bash-4.4#n3970

zz.单词拆分代码现在处理非空格的 IFS 字符, 制表符,或换行符和任何相邻的 IFS 空格作为单个分隔符,如 SUSv3/XPG6 需要。

这记录了"此版本之间的更改,bash-3.1-alpha1, 和以前的版本,bash-3.0-release"——所以你的"它有效"版本的bash一定旧。


说了这么多,我建议的解决方法是:不要使用自定义 IFS,只需考虑您将阅读 3 个单词的事实:

$ read -r missed of total <<<"$ins_data"
$ declare -p missed of total
declare -- missed="3,998"
declare -- of="of"
declare -- total="5,903"
$ echo "${missed//,/}"
3998
$ echo "${total//,/}"
5903

最新更新