Bash:仅在特定字符后将 IFS 设置为 Space?

Bash: set IFS to Space after specific character only?

我正在使用 IFS=', ' 将一串以逗号分隔的文本拆分为一个数组。问题是有时其中一个以逗号分隔的项目包含 space 跟在 : 之后。结果数组包含该项目作为两个单独的数组元素。是否可以将 IFS 设置为仅拆分 ', ' 并忽略包含 ': '(或任何其他字符)的逗号分隔项?

查看下面第一个命令返回的以逗号分隔的字符串,注意第二个项目有 :。请参阅 MarkerNames[1] and MarkerNames[2] 以查看下面第二个命令中不需要的拆分。

$ exiftool -s3 -TracksMarkersName audioFile.wav
Marker1, Tempo: 120.0, Silence, Marker2, Silence.1, Marker3, Silence.2, Marker4, Silence.3, Marker5

$ IFS=', ' read -r -a MarkerNames <<< $(exiftool -s3 -TracksMarkersName audioFile.wav)
$ declare -p MarkerNames
declare -a MarkerNames='([0]="Marker1" [1]="Tempo:" [2]="120.0" [3]="Silence" [4]="Marker2" [5]="Silence.1" [6]="Marker3" [7]="Silence.2" [8]="Marker4" [9]="Silence.3" [10]="Marker5")'

IFS 包含字符的枚举,其中 每个 都可以作为字段分隔符。所以 ", " 说 "any run of spaces or commas separates my fields".

我认为最简单的解决方法是对输出进行预处理,以便在需要的地方进行中断。

IFS='~' MarkerNames=($(exiftool -s3 -TracksMarkersName audioFile.wav | sed 's/, /~/g'))

这当然需要您找到另一个 IFS 值,该值不会出现在您的数据中。如果 Bash 4+ 可用,可以使用换行符和 readarray.

您可以用逗号分隔,然后删除前导/尾随空格:

IFS=',' read -r -a MarkerNames <<< $(exiftool -s3 -TracksMarkersName audioFile.wav)
shopt -s extglob                          # Needed for extended glob
MarkerNames=( "${MarkerNames[@]/#*( )}" ) # Remove leading spaces
MarkerNames=( "${MarkerNames[@]/%*( )}" ) # Remove trailing spaces