情景linux--read命令产生的硬编码问题怎么解决?

发布时间 - 2017-06-21 00:00:00    点击率:

情景

我们知道,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}的区别


# 则需  # 存于  # 还可以  # 尤其是  # 遍历  # 对其  # 用了  # 但却  # 上看  # 重写 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用y主机助手快速搭建网站?  如何将凡科建站内容保存为本地文件?  如何在阿里云香港服务器快速搭建网站?  zabbix利用python脚本发送报警邮件的方法  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  Laravel怎么上传文件_Laravel图片上传及存储配置  javascript基于原型链的继承及call和apply函数用法分析  Laravel怎么实现微信登录_Laravel Socialite第三方登录集成  深入理解Android中的xmlns:tools属性  如何在阿里云ECS服务器部署织梦CMS网站?  如何在阿里云服务器自主搭建网站?  如何在IIS中新建站点并配置端口与物理路径?  大同网页,大同瑞慈医院官网?  在centOS 7安装mysql 5.7的详细教程  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  如何在IIS中配置站点IP、端口及主机头?  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  Python自动化办公教程_ExcelWordPDF批量处理案例  如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?  Laravel Octane如何提升性能_使用Laravel Octane加速你的应用  如何用狗爹虚拟主机快速搭建网站?  想要更高端的建设网站,这些原则一定要坚持!  Laravel中的withCount方法怎么高效统计关联模型数量  如何在不使用负向后查找的情况下匹配特定条件前的换行符  长沙做网站要多少钱,长沙国安网络怎么样?  Laravel如何实现密码重置功能_Laravel密码找回与重置流程  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  如何有效防御Web建站篡改攻击?  Laravel如何配置Horizon来管理队列?(安装和使用)  如何快速生成高效建站系统源代码?  Android实现代码画虚线边框背景效果  JS实现鼠标移上去显示图片或微信二维码  如何破解联通资金短缺导致的基站建设难题?  如何用PHP快速搭建CMS系统?  今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】  如何为不同团队 ID 动态生成多个非值班状态按钮  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  Linux后台任务运行方法_nohup与&使用技巧【技巧】  Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】  Laravel如何使用Telescope进行调试?(安装和使用教程)  Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件  Linux系统命令中tree命令详解  如何快速生成ASP一键建站模板并优化安全性?  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  iOS UIView常见属性方法小结  如何在阿里云高效完成企业建站全流程?