Bash mapfile 的显式起点:同样从零写入,为什么旧数组尾部有时还在

前天 3阅读

一段脚本读取新清单时只收到一行,旧数组有三项。普通 mapfile 执行后只剩新的一项;为了把起点写清楚,加上 -O 0,尾部两项反而留下了。起点数字虽然相同,“是否显式指定起点”还会决定读取前是否清空数组。

下面使用 Bash 4及以上的 mapfile。保存为 demo.sh,执行 bash demo.sh,不要交给 sh。输入由固定 printf 通过进程替换提供,数组只在内存中,不创建文件。-t 用来去掉每条输入末尾的换行。

Bash mapfile 的显式起点:同样从零写入,为什么旧数组尾部有时还在

AI模型生成概念示意:一排表示新清单替换旧内容,另一排表示只覆盖指定位置;非实测截图。

#!/usr/bin/env bash
set -u

replaced=(old-a old-b old-c)
mapfile -t replaced < <(printf '%s\n' new)
[[ ${#replaced[@]} -eq 1 && ${replaced[0]} == new ]] || exit 1
printf 'default: %s\n' "${replaced[*]}"

preserved=(old-a old-b old-c)
mapfile -t -O 0 preserved < <(printf '%s\n' new)
[[ ${#preserved[@]} -eq 3 ]] || exit 1
[[ ${preserved[*]} == 'new old-b old-c' ]] || exit 1
printf 'explicit zero: %s\n' "${preserved[*]}"

middle=(old-a old-b old-c)
mapfile -t -O 1 middle < <(printf '%s\n' new)
[[ ${middle[*]} == 'old-a new old-c' ]] || exit 1
printf 'origin one: %s\n' "${middle[*]}"

appended=(old-a old-b)
mapfile -t -O "${#appended[@]}" appended < <(printf '%s\n' new-a new-b)
[[ ${#appended[@]} -eq 4 ]] || exit 1
[[ ${appended[*]} == 'old-a old-b new-a new-b' ]] || exit 1
printf 'dense append: %s\n' "${appended[*]}"

默认清空和指定覆盖是不同操作

四行输出依次是 default: new、explicit zero: new old-b old-c、origin one: old-a new old-c,以及 dense append: old-a old-b new-a new-b。第一组没有 -O,mapfile 在赋值前清空原数组,然后从索引零放入 new,所以旧尾部全部消失。

第二组显式使用 -O 0,mapfile 保留原数组,再从零开始依次赋值。输入只有一行,于是只覆盖零号元素,原来的一号、二号仍然存在。显式零不是把默认参数写出来那么简单,还切换了是否预先清空的行为。

第三组 -O 1 从一号位置覆盖,得到 old-a、new、old-c。它不会把旧的一号及其后面元素整体右移,也不是常见编辑器里的插入操作。要插入并保留旧项顺序,应另外构造数组,而不能只给 mapfile 一个位置。

追加需要数组索引的前提

第四组数组从零开始连续存放,因此元素数量二恰好等于下一个空闲索引。把这个数量交给 -O,两个新条目就落在索引二、三。这个写法依赖连续索引;如果中间曾删除元素,元素个数可能不等于最大索引加一。

对稀疏数组,先决定是否要保留原索引。需要追加到现有最大索引之后时,应显式确定那个位置;希望把内容重新排成连续清单时,可以先在明确允许重编号的前提下构造新数组。不要把“还有几项”直接当作“下一项放在哪里”。

示例用每组独立数组,避免上一轮读入结果影响下一轮。实际脚本若复用同一个数组变量,应在函数接口中说明本次是替换、覆盖还是追加。特别是短输入和空输入,最容易暴露旧尾部被意外保留的问题。

-t 只处理行末分隔符,不负责忽略空行、校验字段或去除每行两端空格。本文输入简单且可控,实际读取外部清单时仍应单独验收内容格式与生产者是否成功;mapfile 正常读到文件结尾,并不能证明上游已经产生了完整清单。

资料核对日期:2026年10月2日。最终展示代码在 GNU Bash 5.2.37(1)-release 独立运行并通过全部断言;结果对应文中固定输入。

官方参考

文章版权声明:除非注明,否则均为云鹊BLOG原创文章,转载或复制请以超链接形式并注明出处。