情景

我们知道,read命令可以读取文件内容,并把内容赋值给变量。

以如下的数据文件为例。

$ cat data.txt
1 201623210021 wangzhiguo 25
2 201623210022 yangjiangbo 26
3 201623210023 yangzhen 24
4 201623210024 wangdong 23
5 201623210025 songdong 25

以上文件的四列分别为序号(index)、学号(number)、姓名(name)、年龄(age)。用shell脚本读取该文件并输出每行的值:

$ cat read_data.sh
#!/bin/bash

cat data.txt | while read index number name age
do
echo "index:${index}"
echo "number:${number}"
echo "name:${name}"
echo "age:${age}"
echo " "
done

执行脚本,查看结果:

$ sh read_data.sh
index:1
number:201623210021
name:wangzhiguo
age:25 index:2
number:201623210022
name:yangjiangbo
age:26 index:3
number:201623210023
name:yangzhen
age:24 index:4
number:201623210024
name:wangdong
age:23 index:5
number:201623210025
name:songdong
age:25

不知你发现没有,这样的实现方式有着明显的弊端:

  1. 列名(read index number name age)显式地在代码中指定,如果只是想弄清楚数据文件的每列含义,则需要阅读脚本;
  2. 该脚本中指明了每列的名称,如果希望修改各字段的英文名称(比如序号的英文名称希望改为NUMBER)则需要修改脚本,且修改多处;
  3. 该脚本按一定顺序读取数据文件,因此,如果数据文件中的列顺序发生了变化,则依然需要修改脚本;
  4. 如果有其他数据文件需要按此方式读取,则需要根据数据文件的实际情况再重写一个新脚本;

上述实现方式虽然看起来简单,但基于上述的弊端,我们还应对其进行优化。

方案

解决的根本应该是写尽可能通用的脚本,不依赖数据文件本身的列数、列顺序、列名称(含义)等。

可以将数据文件的各字段名称存于该数据文件的首行。当读取数据文件时,首先读取数据文件的首行,以获取各字段名称的列表;读取其它行时,将首行的值与非首行的值进行一一对应即可。

数据文件

$ cat new_data.txt
index number name age
1 201623210021 wangzhiguo 25
2 201623210022 yangjiangbo 26
3 201623210023 yangzhen 24
4 201623210024 wangdong 23
5 201623210025 songdong 25

脚本

$ cat new_read_data.sh
#!/bin/bash

# 读取文件头行,存于一个数组中
tablehead=(`head -n 1 new_data.txt`) # 从文件第二行开始读取,按上述数组顺序读取各字段
tail -n +2 new_data.txt | while read ${tablehead[*]}
do
# 遍历数组的下标,获取tablehead数组的对应值,以及以该值命名的变量的值
for i in `seq 0 $((${#tablehead[@]}-1))`
do
temp=${tablehead[$i]}
echo "${temp}:${!temp}"
done
echo ""
done

结果

$ sh new_read_data.sh
index:1
number:201623210021
name:wangzhiguo
age:25 index:2
number:201623210022
name:yangjiangbo
age:26 index:3
number:201623210023
name:yangzhen
age:24 index:4
number:201623210024
name:wangdong
age:23 index:5
number:201623210025
name:songdong
age:25

要写出更通用的脚本,还可以做一些判断和处理,比如:数据文件作为参数传入、检查数据文件的行数、检查数据文件的列数,等等。

扩展知识

从脚本的改进上看,比原脚本略显复杂,但却更加通用了。

如果觉得阅读脚本吃力,可以有针对性地学习下,尤其是以下知识点:

  • 数组的相关知识:数组长度、数组内容、数组元素等
  • 变量${abc}和${!abc}的区别

情景linux--如何解决read命令产生的硬编码问题的更多相关文章

  1. 【Linux基础】iconv命令详解(编码转换)

    对于给定文件把它的内容从一种编码转换成另一种编码. iconv -f GBK -t UTF- file1 -o file2 //将GBK转换为UTF8,输出到file2.没-o那么会输出到标准输出 i ...

  2. 解决aapt命令在Linux下无法运行的问题

    新的一个项目,需要在Linux下执行aapt命令对apk文件进行处理 开发环境: MacBook-Pro:appSecuity zhang$ uname -a Darwin huijundeMacBo ...

  3. 如何解决Linux 系统下 ifconfig 命令无网络接口 ens33

    今天我在做Redis的哨兵集群模式的时候,以前都是好的,也不知道从什么时候开始就无法连接Redis服务器了,就是运行如下命令,没有效果:redis-server redis.conf,然后在通过命令查 ...

  4. Linux下登录Oracle命令行时删除键^H解决方法

    Linux下登录Oracle命令行时删除键^H解决方法 在linux服务器下登录oracle的控制台,如果输入错误,想用删除键删除时却不能删除,输出的是^H的字符. 方法 用如下的命令可以使删除键生效 ...

  5. Linux 硬盘分区生效命令partprobe

    在Linux中使用fdisk命令进行分区时,有时会遇到"WARNING: Re-reading the partition table failed with error 16: Devic ...

  6. Linux 性能监控之命令行工具

    引言 对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.这些命令行工具可以在各种Linux系统下使用,可以用于监控和查找产生性能问题的原因.这个命令行工具列表提供了足够的 ...

  7. PHP在linux上执行外部命令

    PHP在linux上执行外部命令 一.PHP中调用外部命令介绍二.关于安全问题三.关于超时问题四.关于PHP运行linux环境中命令出现的问题 一.PHP中调用外部命令介绍在PHP中调用外部命令,可以 ...

  8. LINUX重启MYSQL的命令

    LINUX重启MYSQL的命令 标签: mysqllinuxservice脚本web服务server 2010-06-25 10:21 62152人阅读 评论(0) 收藏 举报  分类: Linux( ...

  9. Linux简单的常用命令——纯手打(慢慢积累)

    ==============linux下快捷键==================ctrl+insert 复制shift +insert 粘贴 输入文件名的前三个字母,按tab键自动补全文件名 在vi ...

随机推荐

  1. spring加载资源文件中classpath*与classpath的区别

    在spring和MyBatis继承的时候,配置mapperLocations.一开始配置是这样的. 需要加载路径为com/thomas/base/mapper和com/thomas/bu/mapper ...

  2. Linux指令--traceroute,netstat,ss

    通过traceroute我们可以知道信息从你的计算机到互联网另一端的主机是走的什么路径.当然每次数据包由某一同样的出发点(source)到达某一同样的目的地(destination)走的路径可能会不一 ...

  3. centos 如何关闭防火墙?

    1 查看防火墙状态: 命令: /etc/init.d/iptables status 如果是开着显示内容类是截图 2 临时关闭防火墙: 命令:/etc/init.d/iptables stop     ...

  4. 李忠益TP5商城项目笔记(待完成)

    商品种类的无限极分类 $data=db('goods_type')->field(['*','concat(path,",",id)'=>'paths'])->o ...

  5. 关于word图片显示不全

    问题:在编辑word时,在其中一行插入一张图片,但是显示不全. 原因:给文字行距设置成 [ 固定值 ]的原因. 解决方案:先删除图片,在插入图片的一行右键--> 段落,弹出对话框,找到设置行距的 ...

  6. WEB渗透测试之漏扫神器

    AppScan 对现代 Web 应用程序和服务执行自动化的动态应用程序安全测试(DAST) 和交互式应用程序安全测试 (IAST).支持 Web 2.0. JavaScript 和 AJAX 框架的全 ...

  7. Effective Java 之-----for-each循环优于传统的for循环

    如下代码: enum Face {1,2,3,4,5,6}: ...... Collection<Face> faces = Array.asList(Face.values); for( ...

  8. 20_Python字典总结

    字典: python内置了字典:dic全称dictionary.其他语言中成为map,使用key-value的存储,键-值.具有极快的查找速度类似与我们查字典,我们要查一个字1.从第一页往后翻,知道翻 ...

  9. CSS中的选择器之html选择器和伪类选择器

    1.html选择器(标签选择器) 基本语法: html标签名称{ 属性名:属性值; 属性名:属性值; } 继续在上面的代码中做修改,实例代码: <!DOCTYPE html> <ht ...

  10. 前端开发-DOM

    文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...