bash内置命令mapfile:读取文件内容到数组
bash提供了两个内置命令:readarray和mapfile,它们是同义词。它们的作用是从标准输入读取一行行的数据,然后每一行都赋值给一个数组的各元素。显然,在shell编程中更常用的是从文件、从管道读取,不过也可以从文件描述符中读取数据。
需要先说明的是,shell并不像其它专门的编程语言对数组、列表提供了大量的操作工具,反而直接操作文本文件更为常见(sed、awk等),所以mapfile用的并不多。
1.语法
mapfile [OPTIONS] ARRAY
readarray [OPTIONS] ARRAY
其中options:
-O INDEX :指定从哪个索引号开始存储数据,默认存储数据的起始索引号为0
-n count :最多只拷贝多少行到数组中,如果count=0,则拷贝所有行
-s count :忽略前count行不读取
-c NUM :每读取NUM行就调用一次"-C callback"选项指定的callback程序
-C callback:每读取"-c NUM"选项指定的NUM行就执行一次callback回调程序
-d string :指定读取数据时的行分隔符,默认是换行符
-t :移除尾随行分隔符,默认是换行符
-u fd :指定从文件描述符fd而非标准输入中读取数据
- 如果不指定ARRAY参数,则默认使用数组MAPFILE
- 如果不指定"-O"选项,则在存储数据之前先清空数组(如果该数组已存在)
- 给定了"-C callback"却没有给定"-c NUM"时,则默认为每5000行调用一次回调程序
- 回调程序是在读取给定行数之后,赋值到数组元素之前执行的。所以流程为:"读NUM行-->callback-->赋值"
- 每次调用回调函数时,都将调用callback之前的最后一行数据及其对应的索引号作为回调程序的参数。例如
-c 3 -C callback,则会将索引号2和第3行内容,索引号5和第6行内容作为callback程序的参数 - "-t"去除行尾分隔符,一般来说都是换行符。用其他语言编程过的人都知道行尾换行符有多烦心,但对于shell编程来说,倒是无所谓
2.几个示例和注意事项
先创建一个示例用的文件alpha.log,每行一个小写字母,共26行:
$ echo {a..z} | tr " " "\n" >alpha.log
$ cat alpha.log
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
读取该文件并将每一行存储到数组myarr中(如果不指定,则存储到默认的MAPFILE数组中)。
$ mapfile myarr <alpha.log
$ echo ${myarr[@]}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo ${myarr[2]}
c
既然是读取标准输入,常见的就有以下几种读取形式:
$ mapfile myarr <alpha.log # 1.输入重定向
$ mapfile myarr < <(cat alpha.log) # 2.进程替换
$ cat alpha.log | mapfile myarr # 3.管道传递
第1、2种写法没什么问题,但第3种写法是有问题的。
$ cat alpha.log | mapfile myarr1
$ echo ${#myarr1[@]}
0
从结果中可以看到,myarr1根本就不存在。为什么?我在shell中while循环的陷阱中给出过解释。这里简单说明一下,对于管道组合的多个命令,它们都会放进同一个进程组中,会进入子shell执行相关操作。当执行完毕后,进程组结束,子shell退出。而子shell中设置的环境是不会粘滞到父shell中的(即不会影响父shell),所以myarr1数组是子shell中的数组,回到父shell就消失了。
解决方法是在子shell中操作数组:
$ cat alpha.log | { mapfile myarr1;echo ${myarr1[@]}; }
mapfile可以指定每读取多少行就执行一次的回调函数,并且会将执行回调函数时读取的最后一行和对应的索引号传递给回调函数作为它额外的参数。
一个简单的示例,每读取3行就执行一次echo,注意看下面传递给给echo的参数值。
$ mapfile -c 3 -C "echo" myarr <alpha.log
2 c
5 f
8 i
11 l
14 o
17 r
20 u
23 x
这里的echo就是回调函数。输出结果中每执行一次就有一空行,这是因为文件中数据是分行的,而echo又自带换行功能。所以,可以使用"-t"选项,在每次读取一行后就去掉该行的换行符。
$ mapfile -t -c 3 -C "echo" myarr <alpha.log
2 c
5 f
8 i
11 l
14 o
17 r
20 u
23 x
可以写一个脚本,或者定义一个函数作为回调程序,实现更复杂的功能,但一定要注意,mapfile传递给callback的两个参数总是最后两个参数。例如:
$ myecho(){ echo $@; };mapfile -t -c 3 -C "myecho haha" myarr <alpha.log
haha 2 c
haha 5 f
haha 8 i
haha 11 l
haha 14 o
haha 17 r
haha 20 u
haha 23 x
还可以将多个操作组合起来作为一个回调程序:
$ mapfile -t -c 3 -C "echo haha;echo" myarr<alpha.log
haha
2 c
haha
5 f
haha
8 i
haha
11 l
haha
14 o
haha
17 r
haha
20 u
haha
23 x
bash内置命令mapfile:读取文件内容到数组的更多相关文章
- Bash内置命令exec和重定向
Bash内置命令exec可以替换当前程序而不需要启动一个新的进程,可以改变标准输入和输出而不需要启动一个新的子进程.如果文件用exec打开,read命令就会把文件指针每次指向下一行直到文件的末尾,如果 ...
- bash内置命令的特殊性,后台任务的"本质"
本文解释bash内置命令的特殊性.前台.后台任务的"本质",以及前.后台任务和bash进程.终端的关系.网上没类似的资料,所以都是自己的感悟和总结,如有错误,120分的期待盼请指正 ...
- Linux bash内置命令集
man cd -->查询不到,所以会提示bash的内置命令 . alias bg bind break builtin caller cd command compgen complete c ...
- Bash内置命令
Bash有很多内置命令,因为这些命令是内置的,因此bash不需要在磁盘上为它们定位,执行速度更快. 1)列出所有内置命令列表$enable 2)关闭内置命令test$enable -n test 3) ...
- 哪一个 bash 内置命令能够进行数学运算?
bash shell 的内置命令 let 可以进行整型数的数学运算. #! /bin/bash--let c=a+b--
- 哪一个 bash 内置命令能够进行数学运算?
bash shell 的内置命令 let 可以进行整型数的数学运算. #! /bin/bash - - let c=a+b - -
- PHP 内置函数fgets读取文件
php fgets()函数从文件指针中读取一行 语法: fgets(file,length) 参数 描述 file 必需.规定尧要读取的文件 length 可选 .规定尧都区的字节数.默认是102字 ...
- Linux内置命令
主要Shell内置命令 Shell有很多内置在其源代码中的命令.这些命令是内置的,所以Shell不必到磁盘上搜索它们,执行速度因此加快.不同的Shell内置命令有所不同. A.2.1 bash内置命令 ...
- Shell内置命令
主要Shell内置命令 Shell有很多内置在其源代码中的命令.这些命令是内置的,所以Shell不必到磁盘上搜索它们,执行速度因此加快.不同的Shell内置命令有所不同. A.2.1 bash内置命 ...
随机推荐
- 编译Spark源码
Spark编译有两种处理方式,第一种是通过SBT,第二种是通过Maven.作过Java工作的一般对于Maven工具会比较熟悉,这边也是选用Maven的方式来处理Spark源码编译工作. 在开始编译工作 ...
- linux 解压 压缩 常见命令
压缩命令: .tar tar -cvf 文件名称.tar 文件或者文件夹 .tar.gz tar -zcvf 文件名称.tar.gz 文件或者文件夹 .tar.xz tar -Jcf 文件名称.tar ...
- RAC环境中threads变更后如何确保goldengate继续正常复制
转载:http://www.easyora.net/blog/goldengate_rac_threads_remap.html 当rac节点变更的时候,比如我们添加或者删除了集群中的节点,理所当然会 ...
- 简单的JavaScript图像延迟加载库Echo.js
插件描述:和 Lazy Load 一样,Echo.js 也是一个用于图像延迟加载 JavaScript.不同的是 Lazy Load 是基于 jQuery 的插件,而 Echo.js 不依赖于 jQu ...
- python 特别的生成器表达式
Ⅰ起因 学习python的同学通常会遇到这样一道经典生成器测试题: def gen(): for i in range(4): yield i base = gen() for n in (2,10) ...
- python opencv 处理文件、摄像头、图形化界面
转换成RGB import cv2 import numpy as ny img = ny.zeros( ( 3 , 3 ),ny.float32) img=cv2.cvtColor(img,cv2. ...
- QT汇总
1.QT介绍及其在Linux下的安装 2.windows下安装QT并与visual studio 2017搭建开发环境 参考资料: QT官网资料 QT实战一二三 Qt资料大全 <Qt 实战一二三 ...
- Linux 查找文件内容、替换
有的时候我们经常性的需要在 linux 某一个目录下查找那些文件里包含我们需要查找的字符,那么这个时候就可以使用一些命令来查找,比如说 grep 1.grep 查询 1.1. 主要参数 [option ...
- 我所理解的Android组件化之通信机制
之前写过一篇关于Android组件化的文章,<Android组件化框架设计与实践>,之前没看过的小伙伴可以先点击阅读.那篇文章是从实战中进行总结得来,是公司的一个真实项目进行组件化架构改造 ...
- mysql5.5 五种日期
mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示 D ...