zoukankan      html  css  js  c++  java
  • 情景linux--如何解决read命令产生的硬编码问题

    情景

    我们知道,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}的区别
  • 相关阅读:
    海思HISI 3518EV200 AEC回音消除+ANR语音降噪(转)
    重磅消息 | 2020年最新全栈测试开发技能实战指南(第1期)
    推荐一款Python开源库,技术人必备的造数据神器!
    DevOps研发模式下「产品质量度量」方案实践
    自动化测试实战技巧:「用例失败重试机制」实现方案分享
    C#/VB.NET 在Word中添加条码、二维码
    Java 在PDF中绘制形状(基于Spire.Cloud.SDK for Java)
    Java 添加条码、二维码到Word文档
    Java 添加、下载、读取PDF附件信息(基于Spire.Cloud.SDK for Java)
    Java 添加、提取PDF中的图片
  • 原文地址:https://www.cnblogs.com/signjing/p/6977829.html
Copyright © 2011-2022 走看看