美文网首页Lunix学习
第二十七课 LinuxShell编程五之呈现数据

第二十七课 LinuxShell编程五之呈现数据

作者: Arroganter | 来源:发表于2018-09-05 16:06 被阅读5次

    说明:本文部分内容均摘取自书籍《Linux命令行与shell脚本编程大全》,版权归原作者所有。《Linux命令行与shell脚本编程大全》(第三版)第十五章学习总结

    第十五章:呈现数据

    本章内容

    再探重定向
    标准输入和输出
    报告错误
    丢弃错误
    丢弃数据
    创建日志文件
    
    

    15.1 理解输入和输出

    两种显示脚本输出的方法

    在显示器屏幕上显示输出
    将输出重定向到文件中
    
    

    15.1.1 标准文件描述符

    Linux系统将每个对象当做文件处理,这包括输入和输出进程
    Linux用文件描述符(file descriptor)来标识每个文件对象
    文件描述符是一个非负整数,可以唯一标识回话中打开的文件
    每个进程一次最多可以有九个文件描述符
    出于特殊目的,bash shell保留了前三个文件描述符
    
    

    Linux的标准文件描述符

    文件描述符:缩写:描述
    0:STDIN:标准输入
    1:STDOUT:标准输出
    2:STDERR:标准错误
    
    

    1.STDIN

    STDIN文件描述符代表shell的标准输入
    对终端界面来说,标准输入时键盘
    shell从STDIN文件描述符对应的键盘获得输入,在用户输入时处理每个字符
    使用输入重定向符号(<)时,读取文件并能够提取数据
    
    

    使用cat命令用testfile文件中的行作为输入

    编写testfile文件

    This is first line.
    This is a test line
    This is third line.
    
    

    执行命令

    cat < testfile
    
    

    2.STDOUT

    STDOUT文件描述符代表shell的标准输出
    在终端界面上,标准输出就是终端显示器
    shell的所有输出会被定向到标准输出中,也就是显示器
    默认情况下,大多数bash命令会将输出导向STDOUT文件描述符
    也可以使用输出重定向来改变(>)
    
    

    执行命令

    ls -l > test2
    cat test2
    who >> test2
    cat test2
    ls -al badfile > test3
    cat test3
    
    

    当执行一个错误的命令时,shell并未将错误消息重定向到文件中

    3.STDERR

    shell通过特殊字符的STDERR文件描述符来处理错误消息
    STDERR文件描述符代表shell的标准错误输出
    shell或shell中运行的程序和脚本出错时生成的错误消息都会发送到这个位置
    默认情况下,错误消息也会输出到显示器输出中
    STDERR并不会随着STDOUT的重定向而发生改变
    
    

    15.1.2 重定向错误

    1.只重定向错误

    STDERR文件描述符为2,可以选择只重定向错误消息
    将文件描述符放在重定向符号前
    该值必须紧紧地放在重定向符号前,否则不会生效
    
    

    执行命令

    ls -al badfile 2> test4
    cat test4
    
    

    也可以组合使用STDOUT和STDERR

    执行命令

    ls -la test badtest test2 2> test5
    cat test5
    
    

    2.重定向错误和数据

    如果想重定向错误和正常输出,必须用两个重定向符号
    需要在符号前面放上带重定向数据所对应的文件描述符
    然后指向用于保持数据的输出文件
    
    

    执行命令

    ls -al test test2 test3 badtest 2> test6 1>test7
    cat test6
    cat test7
    
    

    使用特殊符号(&>)将STDOUT和STDERR的输出重定向到同一个输出文件

    执行命令

    ls -al test test2 test3 badtest &>test7
    cat test7
    
    

    15.2 在脚本中重定向输出

    15.2.1 临时重定向

    命令演示:echo "This is an error message" >&2
    命令说明:手动生成错误信息并输出重定向到STDERR

    编写test8.sh脚本

    #!/bin/bash
    echo "This is an error" >&2
    echo "This is normal output"
    
    

    执行命令

    ./test8.sh
    ./test8.sh 2>test9
    cat test9
    
    

    15.2.2 永久重定向

    使用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符

    编写test10.sh脚本

    #!/bin/bash
    exec 1>testout
    
    echo "This is a test of redirecting all output"
    echo "from a script to another file"
    echo "without having to redirect every individual line"
    
    

    执行命令

    ./test10.sh
    cat testout
    
    

    也可以在脚本执行过程中重定向STDOUT

    编写test11.sh脚本

    #!/bin/bash
    exec 2>testerror
    
    echo "this is the start of the script"
    echo "now redirecting all output to another location"
    
    exec 1>testout
    
    echo "Theis out should go to the testout file"
    echo "but this should go to testerror file" >&2
    
    

    执行命令

    ./test11.sh
    cat testout
    cat testerror
    
    

    15.3 在脚本中重定向输入

    命令演示:exec 0< testfile
    命令说明:使用与脚本重定向STDOUT和STDERR相同的方法将STDIN从键盘重定向到其他位置

    编写test12.sh脚本

    #!/bin/bash
    exec 0< testfile
    count=1
    
    while read line
    do
        echo "Line #$count:$line"
        count=$[ $count + 1 ]
    done
    
    

    15.4 创建自己的重定向

    在脚本中重定向输入和输出时,并不局限这3个默认的文件描述符
    在shell中最多可以有9个打开的文件描述符
    可以将其他6个从3~8的文件描述符中的任意一个分配给文件
    
    

    15.4.1 创建输出文件描述符

    使用exec命令来给输出分配文件描述符

    编写test13.sh脚本

    #!/bin/bash
    
    exec 3>test13out
    
    echo "This should display on the monitor"
    echo "and this should be stored in the file" >&3
    echo "Then this should be back on the monitor"
    
    

    执行命令

    ./test13.sh
    cat test13out
    
    

    命令演示:exec 3>>test13out
    命令说明:使用exec命令来讲输出追加到现有文件中

    15.4.2 重定向文件描述符

    在脚本中临时重定向输出,然后恢复默认输出设置

    编写test14.sh脚本

    #!/bin/bash
    
    exec 3>&1
    exec 1>test14out
    
    echo "This should store in the output file"
    echo "along with whis line"
    
    exec 1>&3
    
    echo "Now things should be back normal"
    
    

    执行命令

    ./test14.sh
    cat test14out
    
    

    这个例子有点叫人抓狂,来一段一段地看。首先,脚本将文件描述符 3 重定向到文件描述符1
    的当前位置,也就是 STDOUT 。这意味着任何发送给文件描述符 3 的输出都将出现在显示器上。
    第二个 exec 命令将 STDOUT 重定向到文件,shell现在会将发送给 STDOUT 的输出直接重定向到
    输出文件中。但是,文件描述符 3 仍然指向 STDOUT 原来的位置,也就是显示器。如果此时将输出
    数据发送给文件描述符 3 ,它仍然会出现在显示器上,尽管 STDOUT 已经被重定向了。
    在向 STDOUT (现在指向一个文件)发送一些输出之后,脚本将 STDOUT 重定向到文件描述符
    3 的当前位置(现在仍然是显示器)。这意味着现在 STDOUT 又指向了它原来的位置:显示器。
    这个方法可能有点叫人困惑,但这是一种在脚本中临时重定向输出,然后恢复默认输出设置
    的常用方法。

    15.4.3 创建输入文件描述符

    可以将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它原来的位置

    编写test15.sh脚本

    #!/bin/bash
    
    exec 6<&0
    exec 0< testfile
    
    count=1
    while read line
    do
        echo "Line #$count:$line"
        count=$[ $count+1 ]
    done
    
    exec 0<&6
    read -p "Are you done now [Y/N]?" answer
    case $answer in
    Y|y) echo "Goodbye" ;;
    N|n) echo "Sorry,this is the end."
    esac
    
    

    15.4.4 创建读写文件描述符

    可以用同一个文件描述符对同一个文件进行读写
    在对同一个文件进行数据读写时,shell会维护一个内部指针
    任何读或写都会从指针上次的位置开始
    
    

    编写test16.sh脚本

    #!/bin/bash
    
    exec 3<> testfile
    read line <&3
    echo "Read: $line"
    echo "This is a test line" >&3
    
    

    testfile内容

    This is the first line.
    This is the second line.
    This is the third line.
    
    

    执行命令

    cat testfile
    ./test16.sh
    cat testfile
    
    

    15.4.5 关闭文件描述符

    命令格式:exec 3>&-
    命令说明:在脚本结束前手动关闭文件描述符,将它重定向到特殊符号&-

    在关闭文件描述符时,如果随后在脚本中打开了同一个输出文件,则会覆盖已有文件

    编写test17.sh脚本

    #!/bin/bash
    
    exec 3> test17file
    echo "This is a test line of data" >&3
    exec 3>&-
    
    cat test17file
    
    exec 3> test17file
    echo "This'll be bad" >&3
    
    

    执行命令

    ./test17.sh
    cat test17file
    
    

    15.5 列出打开的文件描述符

    使用lsof命令显示已打开的文件描述符

    编写test18.sh脚本

    #!/bin/bash
    
    exec 3> test18file1
    exec 6> test18file2
    exec 7< testfile
    
    /usr/bin/lsof -a -p $$ -d0,1,2,6,7
    
    

    15.6 阻止命令输出

    可以将STDERR重定向到null文件的特殊文件
    在Linux系统上null文件的标准位置时/dev/null
    重定向到该位置的任何数据都会被丢掉
    通常用于清除日志文件
    
    

    命令演示:cat /dev/null > testfile
    命令说明:清除testfile文件中的数据

    15.7 创建临时文件

    15.7.1 创建本地临时文件

    命令演示:mktemp testing.XXXXXX
    命令说明:mktemp命令创建一个临时文件,会自动用6个字符码替换这6个X,从而保证文件名在目录中是唯一的。且可以创建多个临时文件,每个文件都是唯一的。

    编写test19.sh脚本

    #!/bin/bash
    
    tempfile=$(mktemp test19.XXXXXX)
    
    exec 3>$tempfile
    
    echo "This script writes to temp file $tempfile"
    
    echo "This is the first line" >&3
    echo "This is the second line" >&3
    echo "This is the last line" >&3
    
    exec 3>&-
    
    echo "Done creating temp file.The contents are:"
    cat $tempfile
    rm -f $tempfile 2> /dev/null
    
    

    执行命令

    ./test19.sh
    ls -al test19*
    
    

    15.7.2 在/tmp目录创建临时文件

    使用-t选项强制mktemp命令在系统的临时目录下创建该文件
    mktemp命令会返回该临时文件的全路径
    
    

    编写test20.sh脚本

    #!/bin/bash
    
    tempfile=$(mktemp -t tmp.XXXXXX)
    
    echo "This is a test file." > $tempfile
    echo "This is the second line of the test." >> $tempfile
    echo "The temp file is located at: $tempfile"
    
    cat $tempfile
    rm -f $tempfile
    
    

    15.7.3 创建临时目录

    使用-d选项告诉mktemp命令创建一个临时目录

    编写test21.sh脚本

    #!/bin/bash
    
    tempdir=$(mktemp -d dir.XXXXXX)
    cd $tempdir
    tempfile1=$(mktemp temp.XXXXXX)
    tempfile2=$(mktemp temp.XXXXXX)
    exec 7> $tempfile1
    exec 8> $tempfile2
    
    echo "Sending data to directory $tempdir"
    echo "This is a test line of data for $tempfile1" >&7
    echo "This is a test line of data for $tempfile2" >&8
    
    

    执行命令

    ./test21.sh
    ls -al
    ls -al dir.zKQTCL/
    cat dir.zKQTCL/temp.EZBifQ
    cat dir.zKQTCL/temp.sO4oa4
    
    

    15.8 记录消息

    将输出同时发送到显示器和日志文件
    使用tee命令,相当于管道的一个T型接头
    将从STDIN过来的数据同时发往两处
    一处是STDOUT,另一处时tee命令所指定的文件名:tee filename
    
    

    使用-a选项将数据追加到文件中,数据显示在屏幕上的同时再永久保存在文件中

    编写test22.sh脚本

    #!/bin/bash
    
    tempfile=test22file
    
    echo "This is the start of the test" | tee $tempfile
    echo "This is the second line of the test" | tee -a $tempfile
    echo "This is the end of the test" | tee -a $tempfile
    
    

    执行命令

    ./test22.sh
    cat test22file
    
    

    15.9 实例

    案例说明:文件重定向常见于脚本需要读入文件和输出文件。通过读取.csv格式的数据文件,输出SQL INSERT语句来将数据插入数据库

    编写members.csv文本

    Blum,Richard,123 Main st.,Chicago,IL,60601
    Blum,Barbara,123 Main st.,Chicago,IL,60601
    Bresnahan,Christine,456 Oak Ave.,Columbus,OH,43201
    Bresnahan,Timothy,456 Oak Ave.,Columbus,OH,43201
    
    

    编写test23.sh脚本

    #!/bin/bash
    
    outfile='members.sql'
    IFS=','
    
    while read lname fname address city state zip in ${1}
    do
        cat >> $outfile << EOF
        INSERT INTO members (lname,fname,address,city,state,zip) 
        VALUES('$lname','$fname','$address','$city','$state','$zip');
    EOF
    done
    
    

    执行命令

    ./test23.sh < members.csv
    cat members.sql
    
    

    15.10 小结

    bash shell允许在脚本中创建自己的文件描述符。使用mktemp可以很方便的创建临时目录及文件。tee命令便于将输出同时发送给标准输出和日志文件。

    相关文章

      网友评论

        本文标题:第二十七课 LinuxShell编程五之呈现数据

        本文链接:https://www.haomeiwen.com/subject/yxwawftx.html