Bash: установить IFS на пробел только после определенного символа?

Я использую IFS=', ', чтобы разделить строку текста с разделителями-запятыми на массив. Проблема в том, что иногда один из элементов, разделенных запятыми, содержит пробел после :. Результирующий массив содержит этот элемент как два отдельных элемента массива. Можно ли настроить 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")'

person Urphänomen    schedule 31.08.2017    source источник
comment
Можете ли вы опубликовать минимальный воспроизводимый пример?   -  person tripleee    schedule 31.08.2017
comment
Добавлен. Спасибо @tripleee.   -  person Urphänomen    schedule 31.08.2017


Ответы (2)


IFS содержит перечисление символов, каждый может быть разделителем полей. Итак, ", " говорит: «Мои поля разделяются любыми пробелами или запятыми».

Я думаю, что самый простой обходной путь - это предварительно обработать вывод, чтобы вы получали перерывы там, где хотите.

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

Это, конечно, требует, чтобы вы нашли другое IFS значение, которого нет в ваших данных. Если доступен Bash 4+, можно использовать новую строку и readarray.

person tripleee    schedule 31.08.2017
comment
Обратите внимание, что это устанавливает IFS глобально, а не только на время разделения слов для заполнения MarkerNames. - person chepner; 31.08.2017
comment
@chepner Ой, правда? TIL. Может быть, тогда поместите это в функцию с local IFS. - person tripleee; 31.08.2017

Вы можете разделить запятые и удалить начальные / конечные пробелы:

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
person Renaud Pacalet    schedule 31.08.2017