从命令输出生成关联数组

Generate an associative array from command output

我正在编写一个 zsh 完成函数来完成数据库中的 ID。有一个程序 listnotes 输出这样的列表:

bf848bf6-63d2-474b-a2c0-e7e3c4865ce8   Note Title
aba21e55-22c6-4c50-8bf6-bf3b337468e2   Another one
09ead915-bf2d-449d-a943-ff589e79794a   yet another "one"
...

如何根据 listnotes 命令的输出生成关联数组 note_ids,以便获得这样的关联数组?

( bf848bf6-63d2-474b-a2c0-e7e3c4865ce8 "Note Title" aba21e55-22c6-4c50-8bf6-bf3b337468e2 "Another one" 09ead915-bf2d-449d-a943-ff589e79794a "yet another \"one\"" )

请注意,键中可能有空格。我试图用 sed:

生成一些东西
note_ids=($(listnotes | sed 's/^\(.*\)   \(.*\)$/ ""/'))

但像这样引用字符串似乎行不通,标题中的双引号使它变得更加困难。

试试

typeset -A note_ids
for line in ${(f)"$(listnotes)"}; do
    note_ids+=(${line%% *} ${line#*   })
done
  • ${(f)PARAM}:将$PARAM展开的结果拆分为换行符
  • "$(listnotes)":将listnotes的输出逐字放入展开式。
  • for line in LIST:遍历 LIST 中被 ${(f)…} 分割的项目。
  • note_ids+=(key value):将 key-value 对添加到关联数组 note_ids
  • ${line%% *}:从line的扩展末尾切掉匹配" *"的最大部分(一个space后跟任何东西)。因此,在包含第一个 space 之后删除所有内容,只留下密钥。
  • ${line#* }:从$line的展开开始切掉匹配"* "的最小部分(后面跟三个space的任何东西)。因此,删除密钥和用作分隔符的三个 space。

除了使用参数扩展标志 (f),您还可以使用 read:

逐行读取 listnotes 的输出
listnotes | while read; do 
    note_ids+=(${REPLY%% *} ${REPLY#*   })
done

除非另有说明,否则 read 将读取的值放入 REPLY 参数。