情景

我们知道,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. <global-results>标签来定义全局的<result>

    <global-results> <result name="error">/Error.jsp</result>   <!--   Ac ...

  2. 关于Spring的注入方式

      spring的三种注入方式: 接口注入(不推荐) getter,setter方式注入(比较常用) 构造器注入(死的应用) 关于getter和setter方式的注入: autowire=" ...

  3. 极其蛋疼的if else 中的break用法

    主要原因是if不是循环语句 像这样的: while(...) { ==res) { break; } printf("A"); } 跳出的就是while循环.而不是if判断语句 补 ...

  4. zookeeper 实现分布式锁zookeeper 使用 Curator 示例监听、分布式锁

    下载地址: http://download.csdn.net/download/ttyyadd/10239642

  5. form表单中get和post两种提交方式的区别

    一.form表单中get和post两种提交方式的区别? 1.get提交表单中的内容在链接处是可见的.post不可见 2.post相比于get是安全的 3.post不收限制大小,get有限制大小(黑马视 ...

  6. Git:warning: LF will be replaced by CRLF

    windows中的换行符为 CRLF, 而在linux下的换行符为LF,所以在执行add . 时出现提示,解决办法: $ rm -rf .git // 删除.git $ git config --gl ...

  7. hadoop初学

    Hadoop: 官网(hadoop.apache.org)的定义: 一:Hadoop Common: 为Hadoop其它模块提供通用的支持 二:HDFS: 是Hadoop的分布式文件系统,其特点是高度 ...

  8. 让XtraMessageBox按钮显示中文

    需要定义一个继承子Localizer的类,然后重写GetLocalizedString public class MessboxClass : Localizer { public override ...

  9. wenpack-simple+elementUI配置

    首先跟着element官方文档走一遍 注意把.babelrc改成这样 { "presets": [ ["env", { "modules": ...

  10. Go基础之--排序和查找操作

    排序操作主要都在sort包中,导入就可以使用了import("sort") 常用的操作 sort.Ints:对整数进行排序sort.Strings:对字符串进行排序sort.Flo ...