美文网首页
Linux 命令 & shell 脚本之08(呈现数据)

Linux 命令 & shell 脚本之08(呈现数据)

作者: 轻飘飘D | 来源:发表于2020-09-29 17:35 被阅读0次

    1.Linux的标准文件描述符

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

    2.STDIN

    STDIN文件描述符代表shell的标准输入。对终端界面来说,标准输入是键盘.
    在使用输入重定向符号(<)时,Linux会用重定向指定的文件来替换标准输入文件描述符。
    它会读取文件并提取数据,就如同它是键盘上键入的.
    [oracle@DB02 15]$ cat testfile.txt 
    first line. 
    second line. 
    third line.
    
    [oracle@DB02 15]$ cat < testfile.txt 
    first line. 
    second line. 
    third line.
    

    3.STDOUT

    STDOUT文件描述符代表shell的标准输出。在终端界面上,标准输出就是终端显示器.
    可以用输出重定向来改变.
    
    [oracle@DB02 15]$ ls -l
    total 4
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 06:57 testfile.txt
    
    [oracle@DB02 15]$ ls -l > test2
    
    也可以将数据追加到某个文件。这可以用>>符号来完成
    [oracle@DB02 15]$ who >> test2
    
    [oracle@DB02 15]$ cat test2
    total 4
    -rw-r--r-- 1 oracle oinstall  0 Sep 29 07:02 test2
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 06:57 testfile.txt
    root     tty1         2019-10-15 10:07
    oracle   pts/0        2020-09-25 07:06 (10.3.20.85)
    

    3.STDERR

    問題(命令報錯時無法將信息輸出給 test3)
    [oracle@DB02 15]$ ls -l noexistsfile > test3
    ls: cannot access noexistsfile: No such file or directory
    
    [oracle@DB02 15]$ cat test3
    
    重定向错误命令
    [oracle@DB02 15]$ ls -l noexistsfile 2> test4
    
    [oracle@DB02 15]$ cat test4
    ls: cannot access noexistsfile: No such file or directory
    
    将STDOUT和STDERR消息混杂在同一输出中的例子
    [oracle@DB02 15]$ ls -l testfile.txt noexistsfile 2> test5
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 06:57 testfile.txt
    
    [oracle@DB02 15]$ cat test5
    ls: cannot access noexistsfile: No such file or directory
    
    重定向错误和数据
    [oracle@DB02 15]$ ls -l testfile.txt noexistsfile  2> test6 1> test7
    
    [oracle@DB02 15]$ cat test6
    ls: cannot access noexistsfile: No such file or directory
    
    [oracle@DB02 15]$ cat test7
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 06:57 testfile.txt
    
    可以将STDERR和STDOUT的输出重定向到同一个输出文件。为此bash shell提供了特殊的重定向符号&>
    [oracle@DB02 15]$ ls -l testfile.txt noexistsfile  &> test8
    
    [oracle@DB02 15]$ cat test8
    ls: cannot access noexistsfile: No such file or directory
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 06:57 testfile.txt
    

    4.在脚本中重定向输出(临时重定向)

    如果有意在脚本中生成错误消息,可以将单独的一行输出重定向到STDERR。你所需要做的
    是使用输出重定向符来将输出信息重定向到STDERR文件描述符。在重定向到文件描述符时,你
    必须在文件描述符数字之前加一个&:
    
    [oracle@DB02 15]$ echo "This is an error message" >&2
    This is an error message
    
    $ cat test8.sh 
    #!/bin/bash 
    # testing STDERR messages 
    echo "This is an error" >&2 
    echo "This is normal output"
    
    如果像平常一样运行这个脚本,你可能看不出什么区别。
    $ ./test8.sh 
    This is an error 
    This is normal output
    
    如果你在运行脚本时重定向了STDERR,脚本中所有导向STDERR的文本都会被重定向
    $ ./test8.sh 2> test9 
    This is normal output 
    $ cat test9 
    This is an error
    

    5.在脚本中重定向输出(永久重定向)

    如果脚本中有大量数据需要重定向,那重定向每个echo语句就会很烦琐。取而代之,你可
    以用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符
    
    $ cat test10.sh 
    #!/bin/bash 
    # redirecting all output to a file 
    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 
    This is a test of redirecting all output 
    from a script to another file. 
    without having to redirect every individual line
    
    可以在脚本执行过程中重定向STDOUT。
    $ cat test11.sh 
    #!/bin/bash 
    # redirecting output to different locations 
    exec 2>testerror 
    echo "This is the start of the script" 
    echo "now redirecting all output to another location" 
    exec 1>testout 
    echo "This output should go to the testout file" 
    echo "but this should go to the testerror file" >&2 
    
    $ ./test11.sh 
    This is the start of the script 
    now redirecting all output to another location 
    
    $ cat testout 
    This output should go to the testout file 
    $ cat testerror 
    but this should go to the testerror file
    

    6.在脚本中重定向输入

    你可以使用与脚本中重定向STDOUT和STDERR相同的方法来将STDIN从键盘重定向到其他
    位置。exec命令允许你将STDIN重定向到Linux系统上的文件中:
     exec 0< testfile    --这个命令会告诉shell它应该从文件testfile中获得输入,而不是STDIN
    
    [oracle@DB02 15]$ cat test12.sh 
    #!/bin/bash 
    # redirecting file input 
    exec 0< testfile.txt 
    count=1 
    while read line; do 
     echo "Line #$count: $line" 
     count=$[ $count + 1 ] 
    done
    
    [oracle@DB02 15]$ ./test12.sh
    Line #1: first line.
    Line #2: second line.
    Line #3: third line.
    

    7.创建自己的重定向(创建输出文件描述符)

    在shell中最多可以有9个打开的文件描述符。其他6个从3~8的文件描述符均可用作输入或输出重定向。
    你可以将这些文件描述符中的任意一个分配给文件,然后在脚本中使用它们。
    
    可以用exec命令来给输出分配文件描述符。和标准的文件描述符一样,一旦将另一个文件
    描述符分配给一个文件,这个重定向就会一直有效,直到你重新分配。
    
    $ cat test13 
    #!/bin/bash 
    # using an alternative file descriptor 
    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 
    This should display on the monitor 
    Then this should be back on the monitor 
    
    $ cat test13out 
    and this should be stored in the file
    
    这个脚本用exec命令将文件描述符3重定向到另一个文件。当脚本执行echo语句时,输出内
    容会像预想中那样显示在STDOUT上。但你重定向到文件描述符3的那行echo语句的输出却进入
    了另一个文件。这样你就可以在显示器上保持正常的输出,而将特定信息重定向到文件中(比如
    日志文件)。
    也可以不用创建新文件,而是使用exec命令来将输出追加到现有文件中。
    exec 3>>test13out 
    现在输出会被追加到test13out文件,而不是创建一个新文件
    

    8.创建自己的重定向(重定向文件描述符)

    恢复已重定向的文件描述符。可以分配另外一个文件描述符给标准文件描述
    符,反之亦然。这意味着你可以将STDOUT的原来位置重定向到另一个文件描述符,然后再利用
    该文件描述符重定向回STDOUT。
    
    $ cat test14.sh 
    #!/bin/bash 
    # storing STDOUT, then coming back to it 
    #本将文件描述符3重定向到文件描述符1的当前位置,也就是STDOUT
    exec 3>&1 
    exec 1>test14out 
    echo "This should store in the output file" 
    echo "along with this line."
    #将STDOUT重定向到文件描述符3的当前位置(现在仍然是显示器)。这意味着现在STDOUT又指向了它原来的位置:显示器
    exec 1>&3 
    echo "Now things should be back to normal" 
    
    $ ./test14.sh 
    Now things should be back to normal 
    
    $ cat test14out 
    This should store in the output file 
    along with this line.
    

    9.创建自己的重定向(创建输入文件描述符)

    可以用和重定向输出文件描述符同样的办法重定向输入文件描述符。在重定向到文件之前,
    先将STDIN文件描述符保存到另外一个文件描述符,然后在读取完文件之后再将STDIN恢复到它原来的位置。
    
    [oracle@DB02 15]$ cat test15.sh 
    #!/bin/bash 
    # redirecting input file descriptors 
    #文件描述符6用来保存STDIN的位置
    exec 6<&0 
    exec 0< testfile.txt 
    
    count=1 
    while read line; do 
     echo "Line #$count: $line" 
     count=$[ $count + 1 ] 
    done 
    #将STDIN重定向到文件描述符6,从而将STDIN恢复到原先的位置:键盘的输入
    exec 0<&6 
    
    read -p "Are you done now? " answer 
    
    case $answer in 
     Y|y) echo "Goodbye";; 
     N|n) echo "Sorry, this is the end.";; 
    esac
    ----------------------------------------------------
    [oracle@DB02 15]$ ./test15.sh 
    Line #1: first line.
    Line #2: second line.
    Line #3: third line.
    Are you done now? n
    Sorry, this is the end.
    
    1. 创建自己的重定向(创建读写文件描述符)
    可以打开单个文件描述符来作为输入和输出。可以用同一个文件描述符对同一个文件进行读写。
    不过用这种方法时,你要特别小心。由于你是对同一个文件进行数据读写,shell会维护一个
    内部指针,指明在文件中的当前位置。任何读或写都会从文件指针上次的位置开始。如果不够小
    心,它会产生一些令人瞠目的结果。看看下面这个例子:
    [oracle@DB02 15]$ cat test16.sh 
    #!/bin/bash 
    # testing input/output file descriptor 
    #了exec命令将文件描述符3分配给文件testfile.txt以进行文件读写
    exec 3<> testfile.txt 
    read line <&3 
    echo "Read First: $line" 
    echo "test line" >&3
    
    [oracle@DB02 15]$ cat testfile.txt 
    first line. 
    second line. 
    third line.
    
    [oracle@DB02 15]$ ./test16.sh
    Read First: first line.
    
    [oracle@DB02 15]$ cat testfile.txt 
    first line. 
    test line
    e. 
    third line.
    

    11.关闭文件描述符

    创建了新的输入或输出文件描述符,shell会在脚本退出时自动关闭它们。然而在有些
    情况下,你需要在脚本结束前手动关闭文件描述符。
    要关闭文件描述符,将它重定向到特殊符号&-。脚本中看起来如下:
    exec 3>&-
    
    一旦关闭了文件描述符,就不能在脚本中向它写入任何数据,否则shell会生成错误消息
    $ cat badtest 
    #!/bin/bash 
    # testing closing file descriptors 
    exec 3> test17file 
    echo "This is a test line of data" >&3 
    exec 3>&- 
    echo "This won't work" >&3 
    $ ./badtest 
    ./badtest: 3: Bad file descriptor
    
    1. 阻止命令输出
    在Linux系统上null文件的标准位置是/dev/null。你重定向到该位置的任何数据都会被丢掉,不会显示
    $ ls -l > /dev/null 
    $ cat /dev/null
    
    是避免出现错误消息,也无需保存它们的一个常用方法
    [oracle@DB02 15]$ ls -l testfile.txt noexistsfile   2> /dev/null
    -rw-r--r-- 1 oracle oinstall 39 Sep 29 08:33 testfile.txt
    
    速清除现有文件中的数据--在输入重定向中将/dev/null作为输入文件。由于/dev/null文件不含有任何内容
    [oracle@DB02 15]$ cat /dev/null > testfile.txt 
    
    [oracle@DB02 15]$ cat testfile.txt 
    

    12.创建临时文件(创建本地临时文件)

    mktemp会在本地目录中创建一个文件。要用mktemp命令在本地目录中创建一个临时文件,你只要指定一个文件名模板就行了。
    模板可以包含任意文本文件名,在文件名末尾加上6个X就行了
    
    [oracle@DB02 15]$  mktemp tmp.XXXXXX  --mktemp命令会用6个字符码替换这6个X,从而保证文件名在目录中是唯一的
    tmp.FwegMN
    
    [oracle@DB02 15]$ ls tmp*
    tmp.FwegMN
    
    在脚本中使用mktemp命令时,可能要将文件名保存到变量中,这样就能在后面的脚本中引用了
    $ cat test19.sh 
    #!/bin/bash 
    # creating and using a temp file 
    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 
    This script writes to temp file test19.vCHoya 
    Done creating temp file. The contents are: 
    This is the first line 
    This is the second line. 
    This is the last line. 
    
    $ ls -al test19* 
    -rwxr--r-- 1 rich rich 356 Oct 29 22:03 test19*
    

    13.创建临时文件(在/tmp 目录创建临时文件)

    -t选项会强制mktemp命令来在系统的临时目录来创建该文件。在用这个特性时,
    mktemp命令会返回用来创建临时文件的全路径,而不是只有文件名
    
    [oracle@DB02 15]$  mktemp -t tmp.XXXXXX
    /u01/tmp/tmp.0BPnVH
    
    [oracle@DB02 15]$ ls /u01/tmp/tmp*
    /u01/tmp/tmp.0BPnVH
    
    $ cat test20.sh 
    #!/bin/bash 
    # creating a temp file in /tmp 
    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 
    
    $ ./test20.sh 
    The temp file is located at: /tmp/tmp.Ma3390 
    This is a test file. 
    This is the second line of the test.
    

    14.创建临时目录

    -d选项告诉mktemp命令来创建一个临时目录而不是临时文件。这样你就能用该目录进行任
    何需要的操作了,比如创建其他的临时文件
    $ cat test21.sh 
    #!/bin/bash 
    # using a temporary directory 
    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 
    Sending data to directory dir.ouT8S8 
    $ ls -al
    total 72 
    drwxr-xr-x 3 rich rich 4096 Oct 17 22:20 ./ 
    drwxr-xr-x 9 rich rich 4096 Oct 17 09:44 ../ 
    drwx------ 2 rich rich 4096 Oct 17 22:20 dir.ouT8S8/ 
    -rwxr--r-- 1 rich rich 338 Oct 17 22:20 test21* 
    $ cd dir.ouT8S8 
    
    [dir.ouT8S8]$ ls -al 
    total 16 
    drwx------ 2 rich rich 4096 Oct 17 22:20 ./ 
    drwxr-xr-x 3 rich rich 4096 Oct 17 22:20 ../ 
    -rw------- 1 rich rich 44 Oct 17 22:20 temp.N5F3O6 
    -rw------- 1 rich rich 44 Oct 17 22:20 temp.SQslb7 
    
    [dir.ouT8S8]$ cat temp.N5F3O6 
    This is a test line of data for temp.N5F3O6 
    
    [dir.ouT8S8]$ cat temp.SQslb7 
    This is a test line of data for temp.SQslb7
    
    1. 记录消息(tee)
    tee命令相当于管道的一个T型接头。它将从STDIN过来的数据同时发往两处。一处是STDOUT,另一处是tee命令行所指定的文件名
     tee filename
    
    由于tee会重定向来自STDIN的数据,你可以用它配合管道命令来重定向命令输出。
    $ date | tee testfile 
    Sun Oct 19 18:56:21 EDT 2014 
    $ cat testfile 
    Sun Oct 19 18:56:21 EDT 2014
    
    输出出现在了STDOUT中,同时也写入了指定的文件中。注意,默认情况下,tee命令会在每
    次使用时覆盖输出文件内容,如果你想将数据追加到文件中,必须用-a选项。
    $ date | tee -a testfile
    
    利用这个方法,既能将数据保存在文件中,也能将数据显示在屏幕上。
    $ cat test22.sh 
    #!/bin/bash 
    # using the tee command for logging 
    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 
    This is the start of the test 
    This is the second line of the test 
    This is the end of the test 
    
    $ cat test22file 
    This is the start of the test 
    This is the second line of the test 
    This is the end of the test
    
    1. csv to sql 案例
    $cat test23.sh 
    #!/bin/bash 
    # read file and create INSERT statements for MySQL 
    outfile='members.sql' 
    IFS=',' 
    while read lname fname address city state zip; do 
      cat >> $outfile << EOF 
      INSERT INTO members (lname,fname,address,city,state,zip) VALUES 
      ('$lname', '$fname', '$address', '$city', '$state', '$zip'); 
    EOF 
    done < ${1}
    
    脚本中出现了三处重定向操作
    1: 在done语句中出现的重定向符号:done < ${1}
    2、3:另外两处重定向操作出现在同一条语句中: cat >> $outfile << EOF
    这条语句中包含一个输出追加重定向(双大于号)和一个输入追加重定向(双小于号)。
    输出重定向将cat命令的输出追加到由$outfile变量指定的文件中。cat命令的输入不再取自标准
    输入,而是被重定向到脚本中存储的数据。EOF符号标记了追加到文件中的数据的起止。
    
    在这个例子中,使用以下输入数据文件。
    $ cat 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 < members.csv
    
    在members.sql输出文件中,你会看到如下输出内容。
    $ cat members.sql 
     INSERT INTO members (lname,fname,address,city,state,zip) VALUES ('Blum', 
     'Richard', '123 Main St.', 'Chicago', 'IL', '60601'); 
     INSERT INTO members (lname,fname,address,city,state,zip) VALUES ('Blum', 
     'Barbara', '123 Main St.', 'Chicago', 'IL', '60601'); 
     INSERT INTO members (lname,fname,address,city,state,zip) VALUES ('Bresnahan', 
     'Christine', '456 Oak Ave.', 'Columbus', 'OH', '43201'); 
     INSERT INTO members (lname,fname,address,city,state,zip) VALUES ('Bresnahan', 
     'Timothy', '456 Oak Ave.', 'Columbus', 'OH', '43201');
    

    相关文章

      网友评论

          本文标题:Linux 命令 & shell 脚本之08(呈现数据)

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