Bash脚本执行需要帮助

时间:2014-11-02 23:50:37

标签: linux bash shell

我有一个脚本,它从文件中提取逗号分隔的信息并准备更新语句。该文件设置如下所示:

ID,NAME,DATE,TIME,HOURS,EMPNUMBER
1, Joe, 12/11, 12:45, 5, 333
2, John, 12/12, 16:45, 7, 666

我的脚本将文件作为参数,并从命令行运行,如下所示:

./runScript.sh file.csv

我的脚本代码如下:

for i in ` cat $1 | grep -v “EMPNUMBER” | cut -d',' -f4,5`
do
   time=`echo $i | cut -d',' -f1`
   hours=`echo $i | cut -d',' -f2`
   echo "update jobs.j j set j.time= $time where j.hours=$hours;"

done

我只是好奇为什么,当我运行我的脚本时,它跳过我的文件中的顶行,这是标题信息。显然,这是期望的效果,但为了让我的学习进步,我需要理解为什么从文件中跳过第一行。

有人可以帮助我理解吗? 〜

2 个答案:

答案 0 :(得分:1)

如果您正在学习bash,那么除了解释grep -v "EMPNUM"是导致标题被跳过的原因之外(-v选项意味着找到不包含的行EMPNUM),还有一些其他要指出的内容。首先,良好的bash代码利用bash提供的工具来读取输入和解析数据,而不是依赖于生成子shell来运行其他程序(即cat, grep, cut)。

注意:使用cat, grep, cut没有任何问题,但是认识到bash本身提供的工具与您正在使用的其他3个程序完全相同,这将增强您的编程技能。< / p>

首先,bash提供了内置read,用于从stdin或任何其他文件中读取数据。要阅读文件,您通常会看到while read var1 var2; do... done <"filename"而不是for i in $(cat file) - 原因有很多。接下来,bash不是调用cut...,而是提供parameter expansion/substring extraction来处理将任何文本行解析为任何单个变量。此外,通过明智地选择伴随read的变量,您可以完全消除substring extraction的使用。

以下显示了使用示例中显示的cat, grep, cut方法的bash替代方法。如果您有兴趣学习bash,请试一试,如果您有任何疑问,请告诉我。您可以互换地使用echoprintf作为输出。虽然echo通常更简单,但printf提供了许多优势。值得学习......

#!/bin/bash

## set the datafile name (defaults to 'dat/empdata.dat')
dfn="${1:-dat/empdata.dat}"

## validate that file is readable
[ -r "$dfn" ] || {
    printf "\n error: file not readable '%s'. Usage: %s [filename (dat/empdata.dat)]\n\n" "$dfn" "${0//*\//}"
    exit 1
}

## simple output header for data
printf "\nEmployee data read from file: '%s'\n\n" "$dfn"

## read each line in file, skipping header (where $id = ID)
#  IFS is set to include ',' in addition to default ' \t\n'
while IFS=$' ,\t\n' read -r id nm dt tm hrs eno || [ -n "$hrs" ]; do

    # if header row - skip
    [ "$id" = "ID" ] && continue
    # print out each of the values for the employee
    printf "ID: %s  NAME: %-4s  DATE: %s  TIME: %s  HOURS: %s  EMPNUMBER: %s\n" \
    "$id" "$nm" "$dt" "$tm" "$hrs" "$eno"

done <"$dfn"

输入文件:

$ cat dat/empdata.dat
ID,NAME,DATE,TIME,HOURS,EMPNUMBER
1, Joe, 12/11, 12:45, 5, 333
2, John, 12/12, 16:45, 7, 666

<强>输出:

$ bash empdata.sh

Employee data read from file: 'dat/empdata.dat'

ID: 1  NAME: Joe   DATE: 12/11  TIME: 12:45  HOURS: 5  EMPNUMBER: 333
ID: 2  NAME: John  DATE: 12/12  TIME: 16:45  HOURS: 7  EMPNUMBER: 666

答案 1 :(得分:0)

使用awk,我试过

awk -F ',' '{if(NR==1) for(i=1;i<=NF;i++) a[i]=$i}{if(NR>=2)for(i=1;i<=NF;i++) printf("%s:%s\t",a[i],$i)}{printf("\n")}' file.txt

输出:

ID:1    NAME: Joe   DATE: 12/11 TIME: 12:45 HOURS: 5    EMPNUMBER: 333  
ID:2    NAME: John  DATE: 12/12 TIME: 16:45 HOURS: 7    EMPNUMBER: 666