Linux shell 脚本编程-基础篇 (五)

Linux_Shell脚本学习第二章-命令之乐(上) 一、用cat 进行拼接 1.1 读取文件内容 1.1.1 打印单个文件的内容 $ cat file.txt This is a line inside file.txt This is the second line inside file.txt 1.1.2 打印多个文件的内容 $ cat one.txt two.txt This line is from one.txt This line ... 阅读详情

继 Linux shell 脚本编程-基础篇 (四)

5 呈现数据


到目前为止。所演示的脚本都是通过将数据打印在屏幕上或将数据重定向到文件中来显示信息。本部分内容将展开这个主题,演示如何将脚本的输出重定向
到 Linux 系统的不同位置。


5.1 理解输入和输出
-----------------------------------------------------------------------------------------------------------------------------------------
至此已经知道了两种显示脚本输出的方法:

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

这两种方法要么将数据输出全部显示,要么什么都不显示。但有时将一部分数据在显示器上显示,另一部分数据保存到文件中也是不错的。对此,了解Linux
如何处理输入输出能够帮助将脚本输出放到正确位置。


5.1.1 标准文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
Linux 系统将每个对象当作文件处理。这包括输入和输出进程。Linux 用文件描述符(file descriptor)来标识每个文件对象。文件描述符是一个非负整数,
可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符。出于特殊目的,bash shell 保留了前三个文件描述符(0、1和2),如下表所示

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


这三个特殊文件描述符会处理脚本的输入和输出。shell 用它们将 shell 默认的输入和输出导向到相应的位置。


■ STDIN
-----------------------------------------------------------------------------------------------------------------------------------------
STDIN 文件描述符代表 shell 的标准输入。对终端界面来说,标准输入是键盘。shell 从 STDIN 文件描述符对应的键盘获得输入,在用户输入时处理每个
字符。

在使用输入重定向符号(<)时,Linux 会用重定向指定的文件来替换标准输入文件描述符。它会读取文件并提取数据,就如同它是键盘上键入的。

许多 bash 命令能接受STDIN的输入,尤其是没有在命令行上指定文件的话。下面是个用 cat 命令处理 STDIN 输入的数据的例子:

    [devalone@devalone ~]$ cat
    this is a test
    this is a test
    this is a second test
    this is a second test

当在命令行上只输入 cat 命令时,它会从 STDIN 接受输入。输入一行,cat 命令就会显示出一行。

但也可以通过 STDIN 重定向符号强制 cat 命令接受来自另一个非 STDIN 文件的输入。

    [devalone@devalone 15]$ cat < testfile
    This is the first line.
    This is the second line.
    This is the third line.


■ STDOUT
-----------------------------------------------------------------------------------------------------------------------------------------
STDOUT 文件描述符代表 shell 的标准输出。在终端界面上,标准输出就是终端显示器。shell 的所有输出(包括 shell 中运行的程序和脚本)会被定向到
标准输出中,也就是显示器。

默认情况下,大多数 bash 命令会将输出导向 STDOUT 文件描述符。也可以用输出重定向来改变。

示例:
    [devalone@devalone 15]$ ll > test2
    [devalone@devalone 15]$ cat test2
    总用量 60
    -rwxrwxr-x. 1 devalone devalone 206 1月   4 2018 test10.sh
    -rwxrwxr-x. 1 devalone devalone 286 1月   4 2018 test11.sh
    -rwxrwxr-x. 1 devalone devalone 148 1月   7 13:15 test12.sh
    -rwxrwxr-x. 1 devalone devalone 209 1月   7 13:15 test13.sh
    -rwxrwxr-x. 1 devalone devalone 209 1月   7 13:15 test14.sh
    -rwxrwxr-x. 1 devalone devalone 303 1月   7 13:15 test15.sh
    -rwxrwxr-x. 1 devalone devalone 135 1月   7 13:15 test16.sh
    -rwxrwxr-x. 1 devalone devalone 178 1月   7 13:15 test17.sh
    -rwxrwxr-x. 1 devalone devalone 147 1月   7 13:15 test18.sh
    -rwxrwxr-x. 1 devalone devalone 354 1月   7 13:15 test19.sh
    -rw-rw-r--. 1 devalone devalone   0 7月   8 11:17 test2
    -rwxrwxr-x. 1 devalone devalone 252 1月   7 13:15 test20.sh
    -rwxrwxr-x. 1 devalone devalone 343 1月   7 13:15 test21.sh
    -rwxrwxr-x. 1 devalone devalone 239 1月   7 13:15 test22.sh
    -rwxrwxr-x. 1 devalone devalone  96 1月   4 2018 test8.sh
    -rw-rw-r--. 1 devalone devalone  72 7月   8 11:13 testfile

通过输出重定向符号,通常会显示到显示器的所有输出会被 shell 重定向到指定的重定向文件。也可以将数据追加到某个文件。这可以用 >> 符号来完成。

示例:
    [devalone@devalone 15]$ who >> test2
    [devalone@devalone 15]$ cat test2
    总用量 60
    -rwxrwxr-x. 1 devalone devalone 206 1月   4 2018 test10.sh
    -rwxrwxr-x. 1 devalone devalone 286 1月   4 2018 test11.sh
    -rwxrwxr-x. 1 devalone devalone 148 1月   7 13:15 test12.sh
    -rwxrwxr-x. 1 devalone devalone 209 1月   7 13:15 test13.sh
    -rwxrwxr-x. 1 devalone devalone 209 1月   7 13:15 test14.sh
    -rwxrwxr-x. 1 devalone devalone 303 1月   7 13:15 test15.sh
    -rwxrwxr-x. 1 devalone devalone 135 1月   7 13:15 test16.sh
    -rwxrwxr-x. 1 devalone devalone 178 1月   7 13:15 test17.sh
    -rwxrwxr-x. 1 devalone devalone 147 1月   7 13:15 test18.sh
    -rwxrwxr-x. 1 devalone devalone 354 1月   7 13:15 test19.sh
    -rw-rw-r--. 1 devalone devalone   0 7月   8 11:17 test2
    -rwxrwxr-x. 1 devalone devalone 252 1月   7 13:15 test20.sh
    -rwxrwxr-x. 1 devalone devalone 343 1月   7 13:15 test21.sh
    -rwxrwxr-x. 1 devalone devalone 239 1月   7 13:15 test22.sh
    -rwxrwxr-x. 1 devalone devalone  96 1月   4 2018 test8.sh
    -rw-rw-r--. 1 devalone devalone  72 7月   8 11:13 testfile
    devalone pts/0        2018-07-08 11:11 (192.168.1.101)

who 命令生成的输出会被追加到test2文件中已有数据的后面。

但是,如果对脚本使用了标准输出重定向,会遇到一个问题。

示例:
    [devalone@devalone 15]$ ls -al badfile > test3
    ls: 无法访问'badfile': No such file or directory
    [devalone@devalone 15]$ cat test3

当命令生成错误消息时,shell 并未将错误消息重定向到输出重定向文件。shell 创建了输出重定向文件,但错误消息却显示在了显示器屏幕上。在显示
test3 文件的内容时并没有任何错误。test3 文件创建成功了,只是里面是空的。

shell 对于错误消息的处理是跟普通输出分开的。如果创建了在后台模式下运行的 shell 脚本,通常必须依赖发送到日志文件来输出消息。用这种方法,
如果出现了错误信息,这些信息是不会出现在日志文件中的。需要换种方法来处理。


■ STDERR
-----------------------------------------------------------------------------------------------------------------------------------------
shell 通过特殊的 STDERR 文件描述符来处理错误消息。STDERR 文件描述符代表 shell 的标准错误输出。shell 或 shell 中运行的程序和脚本出错时生成
的错误消息都会发送到这个位置。

默认情况下,STDERR 文件描述符会和 STDOUT 文件描述符指向同样的地方(尽管分配给它们的文件描述符值不同)。也就是说,默认情况下,错误消息也会
输出到显示器输出中。

但从上面的例子可以看出,STDERR 并不会随着 STDOUT 的重定向而发生改变。使用脚本时,常常会想改变这种行为,尤其是当希望将错误消息保存到日志文
件中的时候。


5.1.2 重定向错误
-----------------------------------------------------------------------------------------------------------------------------------------
已经知道如何用重定向符号来重定向 STDOUT 数据。重定向 STDERR 数据也没太大差别,只要在使用重定向符号时定义 STDERR 文件描述符就可以了。有几种
实现方法。


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

示例:
    [devalone@devalone 15]$ ls -al badfile 2> test4
    [devalone@devalone 15]$ cat test4
    ls: 无法访问'badfile': No such file or directory

现在运行该命令,错误消息不会出现在屏幕上了。该命令生成的任何错误消息都会保存在输出文件中。用这种方法,shell 会只重定向错误消息,而非普通
数据。

将 STDOUT 和 STDERR 消息混杂在同一输出中的例子:

    [devalone@devalone 15]$ ls -al test badtest test2 2> test5
    -rw-rw-r--. 1 devalone devalone 1035 7月   8 11:18 test2
    [devalone@devalone 15]$ cat test5
    ls: 无法访问'test': No such file or directory
    ls: 无法访问'badtest': No such file or directory

ls 命令的正常 STDOUT 输出仍然会发送到默认的 STDOUT 文件描述符,也就是显示器。由于该命令将文件描述符 2 的输出(STDERR)重定向到了一个输出
文件,shell 会将生成的所有错误消息直接发送到指定的重定向文件中。


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

示例:
    [devalone@devalone 15]$ ls -al test test2 test3 badtest 2> test6 1> test7
    [devalone@devalone 15]$ cat test6
    ls: 无法访问'test': No such file or directory
    ls: 无法访问'badtest': No such file or directory
    [devalone@devalone 15]$ cat test7
    -rw-rw-r--. 1 devalone devalone 1035 7月   8 11:18 test2
    -rw-rw-r--. 1 devalone devalone    0 7月   8 11:21 test3

shell利用 1> 符号将ls命令的正常输出重定向到了 test7 文件,而这些输出本该是进入 STDOUT 的。所有本该输出到 STDERR 的错误消息通过 2> 符号被
重定向到了 test6 文件。

可以用这种方法将脚本的正常输出和脚本生成的错误消息分离开来。这样就可以轻松地识别出错误信息,再不用在成千上万行正常输出数据中翻腾了。

另外,也可以将 STDERR 和 STDOUT 的输出重定向到同一个输出文件。为此 bash shell 提供了特殊的重定向符号 &> 。

示例:
    [devalone@devalone 15]$ ls -al test test2 test3 badtest &> test7
    [devalone@devalone 15]$ cat test7
    ls: 无法访问'test': No such file or directory
    ls: 无法访问'badtest': No such file or directory
    -rw-rw-r--. 1 devalone devalone 1035 7月   8 11:18 test2
    -rw-rw-r--. 1 devalone devalone    0 7月   8 11:21 test3

当使用 &> 符号时,命令生成的所有输出都会发送到同一位置,包括数据和错误。其中有一条错误消息出现的位置和预想中的不一样。badtest 文件(列出的
最后一个文件)的这条错误消息出现在输出文件中的第二行。

为了避免错误信息散落在输出文件中,相较于标准输出,bash shell 自动赋予了错误消息更高的优先级。这样能够集中浏览错误信息。

 

5.2 在脚本中重定向输出
-----------------------------------------------------------------------------------------------------------------------------------------
可以在脚本中用 STDOUT 和 STDERR 文件描述符在多个位置生成输出,只要简单地重定向相应的文件描述符就行了。有两种方法来在脚本中重定向输出:

    □ 临时重定向行输出
    □ 永久重定向脚本中的所有命令

 

5.2.1 临时重定向
-----------------------------------------------------------------------------------------------------------------------------------------
如果有意在脚本中生成错误消息,可以将单独的一行输出重定向到 STDERR。所需要做的是使用输出重定向符来将输出信息重定向到 STDERR 文件描述符。
在重定向到文件描述符时,必须在文件描述符数字之前加一个 &:

示例:

    echo "This is an error message" >&2

这行会在脚本的 STDERR 文件描述符所指向的位置显示文本,而不是通常的 STDOUT。

示例:
    [devalone@devalone 15]$ cat test8.sh
    #!/bin/bash
    # testing STDERR messages

    echo "This is an error" >&2
    echo "This is normal output"

如果像平常一样运行这个脚本,可能看不出什么区别:
运行:
    [devalone@devalone 15]$ ./test8.sh
    This is an error
    This is normal output

记住,默认情况下,Linux 会将 STDERR 导向 STDOUT。但是,如果在运行脚本时重定向了 STDERR,脚本中所有导向 STDERR 的文本都会被重定向。

运行:
    [devalone@devalone 15]$ ./test8.sh 2> test9
    This is normal output
    [devalone@devalone 15]$ cat test9
    This is an error

通过 STDOUT 显示的文本显示在了屏幕上,而发送给 STDERR 的 echo 语句的文本则被重定向到了输出文件。

这个方法非常适合在脚本中生成错误消息。如果有人用了的脚本,他们可以像上面的例子中那样轻松地通过 STDERR 文件描述符重定向错误消息。


5.2.2 永久重定向
-----------------------------------------------------------------------------------------------------------------------------------------
如果脚本中有大量数据需要重定向,那重定向每个 echo 语句就会很烦琐。取而代之,可以用 exec 命令告诉 shell 在脚本执行期间重定向某个特定文件
描述符。

示例:
    [devalone@devalone 15]$ 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"

运行:
    [devalone@devalone 15]$ ./test10.sh
    [devalone@devalone 15]$ cat testout
    This is a test of redirecting all output
    from a script to another file.
    without having to redirect every individual line

exec 命令会启动一个新 shell 并将 STDOUT 文件描述符重定向到文件。脚本中发给 STDOUT 的所有输出会被重定向到文件。

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

    [devalone@devalone 15]$ 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

运行:
    [devalone@devalone 15]$ test11.sh
    This is the start of the script
    now redirecting all output to another location

    [devalone@devalone 15]$ cat testout
    This output should go to the testout file
    [devalone@devalone 15]$ cat testerror
    but this should go to the testerror file

这个脚本用 exec 命令来将发给 STDERR 的输出重定向到文件 testerror。接下来,脚本用 echo 语句向 STDOUT 显示了几行文本。随后再次使用 exec
命令来将 STDOUT 重定向到 testout 文件。注意,尽管 STDOUT 被重定向了,但仍然可以将 echo 语句的输出发给 STDERR,在本例中还是重定向到
testerror 文件。

当只想将脚本的部分输出重定向到其他位置时(如错误日志),这个特性用起来非常方便。


5.3 在脚本中重定向输入
-----------------------------------------------------------------------------------------------------------------------------------------
可以使用与脚本中重定向 STDOUT 和 STDERR 相同的方法来将 STDIN 从键盘重定向到其他位置。exec 命令允许将 STDIN 重定向到Linux系统上的文件中:

    exec 0< testfile
    
这个命令会告诉 shell 它应该从文件 testfile 中获得输入,而不是 STDIN。这个重定向只要在脚本需要输入时就会作用。

示例:

    [devalone@devalone 15]$ cat test12.sh
    #!/bin/bash
    #
    # redirecting file input
    #

    exec 0< testfile
    count=1

    while read line
    do
        echo "Lin #$count: $line"
        count=$[ $count + 1 ]
    done

运行:
    [devalone@devalone 15]$ test12.sh
    Lin #1: This is the first line.
    Lin #2: This is the second line.
    Lin #3: This is the third line.

将 STDIN 重定向到文件后,当 read 命令试图从 STDIN 读入数据时,它会到文件去取数据,而不是键盘。

这是在脚本中从待处理的文件中读取数据的绝妙办法。Linux 系统管理员的一项日常任务就是从日志文件中读取数据并处理。这是完成该任务最简单的办法。


5.4 创建自己的重定向
-----------------------------------------------------------------------------------------------------------------------------------------
在脚本中重定向输入和输出时,并不局限于这 3 个默认的文件描述符。曾提到过,在 shell 中最多可以有 9 个打开的文件描述符。其他 6 个从 3~8 的文
件描述符均可用作输入或输出重定向。可以将这些文件描述符中的任意一个分配给文件,然后在脚本中使用它们。


5.4.1 创建输出文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
可以用 exec命令来给输出分配文件描述符。和标准的文件描述符一样,一旦将另一个文件描述符分配给一个文件,这个重定向就会一直有效,直到重新分配。

示例:
    [devalone@devalone 15]$ cat test13.sh
    #!/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"

运行:
    [devalone@devalone 15]$ test13.sh
    This should display on the monitor
    Then this should be back on the monitor

    [devalone@devalone 15]$ cat test13out
    and this should be stored in the file

这个脚本用 exec 命令将文件描述符 3 重定向到另一个文件。当脚本执行 echo 语句时,输出内容会像预想中那样显示在 STDOUT上。但重定向到文件
描述符 3 的那行 echo 语句的输出却进入了另一个文件。这样就可以在显示器上保持正常的输出,而将特定信息重定向到文件中(比如日志文件)。

也可以不用创建新文件,而是使用 exec 命令来将输出追加到现有文件中。

    exec 3>>test13out

现在输出会被追加到 test13out 文件,而不是创建一个新文件。


5.4.2 重定向文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
现在介绍怎么恢复已重定向的文件描述符。可以分配另外一个文件描述符给标准文件描述符,反之亦然。这意味着可以将 STDOUT 的原来位置重定向到另一个
文件描述符,然后再利用该文件描述符重定向回 STDOUT。

示例:
    [devalone@devalone 15]$ cat test14.sh
    #!/bin/bash
    # storing STDOUT, then coming back to it

    exec 3>&1
    exec 1>test14out

    echo "This should store in the output file"
    echo "alone with this line"

    exec 1>&3

    echo "Now things should be back to normal"

运行:
    [devalone@devalone 15]$ test14.sh
    Now things should be back to normal

    [devalone@devalone 15]$ cat test14out
    This should store in the output file
    alone with this line

首先,脚本将文件描述符 3 重定向到文件描述符 1 的当前位置,也就是 STDOUT。这意味着任何发送给文件描述符 3 的输出都将出现在显示器上。

第二个 exec 命令将 STDOUT 重定向到文件,shell 现在会将发送给 STDOUT的输出直接重定向到输出文件中。但是,文件描述符 3 仍然指向 STDOUT 原来
的位置,也就是显示器。如果此时将输出数据发送给文件描述符 3,它仍然会出现在显示器上,尽管 STDOUT 已经被重定向了。

在向 STDOUT(现在指向一个文件)发送一些输出之后,脚本将 STDOUT 重定向到文件描述符 3 的当前位置(现在仍然是显示器)。这意味着现在 STDOUT又
指向了它原来的位置:显示器。

这个方法可能有点叫人困惑,但这是一种在脚本中临时重定向输出,然后恢复默认输出设置的常用方法。


5.4.3 创建输入文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
可以用和重定向输出文件描述符同样的办法重定向输入文件描述符。在重定向到文件之前,先将 STDIN 文件描述符保存到另外一个文件描述符,然后在读取
完文件之后再将 STDIN 恢复到它原来的位置。

示例:
    [devalone@devalone 15]$ cat test15.sh
    #!/bin/bash
    # redirecting input file descriptors

    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? " answer
    case $answer in
        Y|y) echo "Goodby";;
        N|n) echo "Sorry, this is the end.";;
    esac

运行:
    [devalone@devalone 15]$ test15.sh
    Line #1: This is the first line.
    Line #2: This is the second line.
    Line #3: This is the third line.
    Are you done now? y
    Goodby

在这个例子中,文件描述符 6 用来保存 STDIN 的位置。然后脚本将 STDIN 重定向到一个文件。read 命令的所有输入都来自重定向后的 STDIN(也就是
输入文件)。

在读取了所有行之后,脚本会将 STDIN 重定向到文件描述符6,从而将 STDIN 恢复到原先的位置。该脚本用了另外一个 read 命令来测试 STDIN是否恢复
正常了。这次它会等待键盘的输入。


5.4.4 创建读写文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
可以打开单个文件描述符来作为输入和输出。可以用同一个文件描述符对同一个文件进行读写。

不过用这种方法时,要特别小心。由于是对同一个文件进行数据读写,shell 会维护一个内部指针,指明在文件中的当前位置。任何读或写都会从文件指针
上次的位置开始。如果不够小心,它会产生一些令人困惑的结果。

示例:
    [devalone@devalone 15]$ cat test16.sh
    #!/bin/bash
    # testing input/output file descriptor

    exec 3<> testfile

    read line <&3
    echo "Read: $line"
    echo "This is a test line" >&3
    
运行:
    [devalone@devalone 15]$ cat testfile
    This is the first line.
    This is the second line.
    This is the third line.
    
    [devalone@devalone 15]$ test16.sh
    Read: This is the first line.
    
    [devalone@devalone 15]$ cat testfile
    This is the first line.
    This is a test line
    ine.
    This is the third line.

这个例子用了 exec 命令将文件描述符 3 分配给文件 testfile 以进行文件读写。接下来,它通过分配好的文件描述符,使用 read 命令读取文件中的
第一行,然后将这一行显示在 STDOUT 上。最后,它用 echo 语句将一行数据写入由同一个文件描述符打开的文件中。

在运行脚本时,一开始还算正常。输出内容表明脚本读取了 testfile 文件中的第一行。但如果在脚本运行完毕后,查看 testfile 文件内容的话,会发现
写入文件中的数据覆盖了已有的数据。

当脚本向文件中写入数据时,它会从文件指针所处的位置开始。read 命令读取了第一行数据,所以它使得文件指针指向了第二行数据的第一个字符。在 echo
语句将数据输出到文件时,它会将数据放在文件指针的当前位置,覆盖了该位置的已有数据。


5.4.5 关闭文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
如果创建了新的输入或输出文件描述符,shell 会在脚本退出时自动关闭它们。然而在有些情况下,需要在脚本结束前手动关闭文件描述符。

要关闭文件描述符,将它重定向到特殊符号 &- 。脚本中看起来如下:

    exec 3>&-

该语句会关闭文件描述符 3,不再在脚本中使用它。

示例:
    [devalone@devalone 15]$ cat badtest.sh
    #!/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

运行:
    [devalone@devalone 15]$ badtest.sh
    ./badtest.sh:行6: 3: Bad file descriptor

一旦关闭了文件描述符,就不能在脚本中向它写入任何数据,否则 shell 会生成错误消息。

在关闭文件描述符时还要注意另一件事。如果随后在脚本中打开了同一个输出文件,shell 会用一个新文件来替换已有文件。这意味着如果输出数据,它就
会覆盖已有文件。

    [devalone@devalone 15]$ cat test17.sh
    #!/bin/bash
    # testing closing file descriptors

    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

运行:
    [devalone@devalone 15]$ test17.sh
    This is a test line of data
    [devalone@devalone 15]$ cat test17file
    This'll be bad

在向 test17file 文件发送一个数据字符串并关闭该文件描述符之后,脚本用了 cat 命令来显示文件的内容。到目前为止,一切都还好。下一步,脚本重新
打开了该输出文件并向它发送了另一个数据字符串。当显示该输出文件的内容时,所能看到的只有第二个数据字符串。shell 覆盖了原来的输出文件。


5.5 列出打开的文件描述符
-----------------------------------------------------------------------------------------------------------------------------------------
能用的文件描述符只有 9 个,有时要记住哪个文件描述符被重定向到了哪里很难。为了帮助理清条理,bash shell 提供了 lsof 命令。

lsof 命令会列出整个 Linux 系统打开的所有文件描述符。这是个有争议的功能,因为它会向非系统管理员用户提供 Linux 系统的信息。鉴于此,许多Linux
系统隐藏了该命令,这样用户就不会一不小心就发现了。

在很多 Linux系统中(如Fedora),要想以普通用户账户来运行它,必须通过全路径名来引用:

    [devalone@devalone 15]$ which lsof
    /usr/bin/lsof

该命令会产生大量的输出。它会显示当前 Linux 系统上打开的每个文件的有关信息。这包括后台运行的所有进程以及登录到系统的任何用户。

有大量的命令行选项和参数可以用来帮助过滤 lsof 的输出。最常用的有 -p 和 -d,前者允许指定进程ID(PID),后者允许指定要显示的文件描述符编号。
要想知道进程的当前PID,可以用特殊环境变量$$(shell会将它设为当前PID)。-a 选项用来对其他两个选项的结果执行布尔AND运算,这会产生如下输出:

    [devalone@devalone 15]$ lsof -a -p $$ -d 0,1,2
    COMMAND  PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    bash    2291 devalone    0u   CHR  136,0      0t0    3 /dev/pts/0
    bash    2291 devalone    1u   CHR  136,0      0t0    3 /dev/pts/0
    bash    2291 devalone    2u   CHR  136,0      0t0    3 /dev/pts/0

上例显示了当前进程(bash shell)的默认文件描述符(0、1 和 2)。lsof 的默认输出中有 7 列信息,如下表所示:


    lsof 的默认输出
    +-----------+---------------------------------------------------------------------------------------
    | 列        | 描 述
    +-----------+---------------------------------------------------------------------------------------
    | COMMAND    | 正在运行的命令名的前9个字符
    +-----------+---------------------------------------------------------------------------------------
    | PID        | 进程的PID
    +-----------+---------------------------------------------------------------------------------------
    | USER        | 进程属主的登录名
    +-----------+---------------------------------------------------------------------------------------
    | FD        | 文件描述符号以及访问类型(r代表读,w代表写,u代表读写)
    +-----------+---------------------------------------------------------------------------------------
    | TYPE        | 文件的类型(CHR代表字符型,BLK代表块型,DIR代表目录,REG代表常规文件)
    +-----------+---------------------------------------------------------------------------------------
    | DEVICE    | 设备的设备号(主设备号和从设备号)
    +-----------+---------------------------------------------------------------------------------------
    | SIZE        | 如果有的话,表示文件的大小
    +-----------+---------------------------------------------------------------------------------------
    | NODE        | 本地文件的节点号
    +-----------+---------------------------------------------------------------------------------------
    | NAME        | 文件名
    +-----------+---------------------------------------------------------------------------------------


与 STDIN、STDOUT 和 STDERR 关联的文件类型是字符型。因为 STDIN、STDOUT 和 STDERR文件描述符都指向终端,所以输出文件的名称就是终端的设备名。
所有 3 种标准文件都支持读和写(尽管向 STDIN 写数据以及从 STDOUT 读数据看起来有点奇怪)。

看一下在打开了多个替代性文件描述符的脚本中使用 lsof 命令的结果:

    [devalone@devalone 15]$ cat test18.sh
    #!/bin/bash
    # testing lsof with file descripters

    exec 3> test18file1
    exec 6> test18file2
    exec 7< testfile

    lsof -a -p $$ -d 0,1,2,3,6,7

运行:
    [devalone@devalone 15]$ test18.sh
    COMMAND    PID     USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
    test18.sh 2476 devalone    0u   CHR  136,0      0t0       3 /dev/pts/0
    test18.sh 2476 devalone    1u   CHR  136,0      0t0       3 /dev/pts/0
    test18.sh 2476 devalone    2u   CHR  136,0      0t0       3 /dev/pts/0
    test18.sh 2476 devalone    3w   REG  253,2        0 2497622 /home/devalone/study/shell-script/15/test18file1
    test18.sh 2476 devalone    6w   REG  253,2        0 2497623 /home/devalone/study/shell-script/15/test18file2
    test18.sh 2476 devalone    7r   REG  253,2       74 2497619 /home/devalone/study/shell-script/15/testfile
    [devalone@devalone 15]$

该脚本创建了 3 个替代性文件描述符,两个作为输出(3和6),一个作为输入(7)。在脚本运行 lsof 命令时,可以在输出中看到新的文件描述符。文件名
显示了文件描述符所使用的文件的完整路径名。它将每个文件都显示成 REG 类型的,这说明它们是文件系统中的常规文件。


5.6 阻止命令输出
-----------------------------------------------------------------------------------------------------------------------------------------
有时候,可能不想显示脚本的输出。这在将脚本作为后台进程运行时很常见。如果在运行在后台的脚本出现错误消息,shell 会通过电子邮件将它们发给进程
的属主。这会很麻烦,尤其是当运行会生成很多烦琐的小错误的脚本时。

要解决这个问题,可以将 STDERR 重定向到一个叫作 null 文件的特殊文件。null 文件跟它的名字很像,文件里什么都没有。shell 输出到 null 文件的任
何数据都不会保存,全部都被丢掉。

在 Linux 系统上 null 文件的标准位置是 /dev/null。重定向到该位置的任何数据都会被丢掉,不会显示。

示例:
    [devalone@devalone 15]$ ll > /dev/null
    [devalone@devalone 15]$ cat /dev/null
    [devalone@devalone 15]$

这是避免出现错误消息,也无需保存它们的一个常用方法:
    
    [devalone@devalone 15]$ ls -al badfile test16 2> /dev/null
    -rw-rw-r--. 1 devalone devalone 43 7月   8 13:27 test16

也可以在输出重定向中将 /dev/null 作为输入文件。由于 /dev/null 文件不含有任何内容,通常用它来快速清除现有文件中的数据,而不用先删除文件再
重新创建:

    [devalone@devalone 15]$ cat testfile
    This is the first line.
    This is a test line
    ine.
    This is the third line.
    [devalone@devalone 15]$ cat /dev/null > testfile
    [devalone@devalone 15]$ cat testfile
    [devalone@devalone 15]$

文件 testfile 仍然存在系统上,但现在它是空文件。这是清除日志文件的一个常用方法,因为日志文件必须时刻准备等待应用程序操作。


5.7 创建临时文件
-----------------------------------------------------------------------------------------------------------------------------------------
Linux 系统有特殊的目录,专供临时文件使用。Linux 使用 /tmp 目录来存放不需要永久保留的文件。大多数 Linux 发行版配置了系统在启动时自动删除
/tmp 目录的所有文件。

系统上的任何用户账户都有权限在读写 /tmp 目录中的文件。这个特性为用户提供了一种创建临时文件的简单方法,而且还不用操心清理工作。

有个特殊命令可以用来创建临时文件。 mktemp 命令可以在 /tmp 目录中创建一个唯一的临时文件。shell 会创建这个文件,但不用默认的 umask 值。它会
将文件的读和写权限分配给文件的属主,并将创建用户设成文件的属主。一旦创建了文件,创建用户就在脚本中有了完整的读写权限,但其他人没法访问它
(当然,root用户除外)。


5.7.1 创建本地临时文件
-----------------------------------------------------------------------------------------------------------------------------------------
默认情况下,mktemp 会在本地目录中创建一个文件。要用 mktemp 命令在本地目录中创建一个临时文件,只要指定一个文件名模板就行了。模板可以包含
任意文本文件名,在文件名末尾加上 6 个X就行了。

    [devalone@devalone 15]$ mktemp testing.XXXXXX
    testing.846nnk

mktemp 命令会用 6 个字符码替换这 6 个X,从而保证文件名在目录中是唯一的。可以创建多个临时文件,它可以保证每个文件都是唯一的。

    [devalone@devalone 15]$ mktemp testing.XXXXXX
    testing.5KFsRw
    [devalone@devalone 15]$ mktemp testing.XXXXXX
    testing.jeVY9y
    [devalone@devalone 15]$ mktemp testing.XXXXXX
    testing.sBokD1

    [devalone@devalone 15]$ ll testing.*
    -rw-------. 1 devalone devalone 0 7月   8 14:31 testing.5KFsRw
    -rw-------. 1 devalone devalone 0 7月   8 14:30 testing.846nnk
    -rw-------. 1 devalone devalone 0 7月   8 14:31 testing.jeVY9y
    -rw-------. 1 devalone devalone 0 7月   8 14:31 testing.sBokD1

mktemp 命令的输出正是它所创建的文件的名字。在脚本中使用 mktemp 命令时,可能要将文件名保存到变量中,这样就能在后面的脚本中引用了。

示例:
    [devalone@devalone 15]$ 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 content are:"
    cat $tempfile
    rm -f $tempfile 2> /dev/null

运行:
    [devalone@devalone 15]$ test19.sh
    This script writes to temp file test19.VnZtPM
    Done creating temp file. The content are:
    This is the first line
    This is the second line
    This is the last line.

脚本用 mktemp 命令来创建临时文件并将文件名赋给 $tempfile 变量。接着将这个临时文件作为文件描述符 3 的输出重定向文件。在将临时文件名显示在
STDOUT 之后,向临时文件中写入了几行文本,然后关闭了文件描述符。最后,显示出临时文件的内容,并用 rm 命令将其删除。


5.7.2 在/tmp 目录创建临时文件
-----------------------------------------------------------------------------------------------------------------------------------------
-t 选项会强制 mktemp 命令来在系统的临时目录来创建该文件。在用这个特性时,mktemp 命令会返回用来创建临时文件的全路径,而不是只有文件名。

示例:
    [devalone@devalone 15]$ mktemp -t test.XXXXXX
    /tmp/test.8kIS22
    [devalone@devalone 15]$ ll -a /tmp/test*
    -rw-------. 1 devalone devalone 0 7月   8 14:38 /tmp/test.8kIS22

由于 mktemp 命令返回了全路径名,可以在 Linux 系统上的任何目录下引用该临时文件,不管工作目录在哪里。

示例:
    [devalone@devalone 15]$ 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

运行:
    [devalone@devalone 15]$ test20.sh
    The temp file is located at: /tmp/tmp.5IljPD
    This is a test file.
    This is the second line of the test.


5.7.3 创建临时目录
-----------------------------------------------------------------------------------------------------------------------------------------
-d 选项告诉 mktemp 命令来创建一个临时目录而不是临时文件。这样就能用该目录进行任何需要的操作了,比如创建其他的临时文件。

示例:
    [devalone@devalone 15]$ cat test21.sh
    #!/bin/bash
    # using a temporary directory

    tempdir=$(mktemp -d dir.XXXXXX)
    cd $tempdir
    tempfile1=$(mktemp temp.XXXXXX)
    tempfile2=$(mktemp temp.XXXXXXXX)

    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

运行:
    [devalone@devalone 15]$ test21.sh
    Sending data to directory dir.lk5PBB

    [devalone@devalone 15]$ cd dir.lk5PBB
    [devalone@devalone dir.lk5PBB]$ ll
    总用量 8
    -rw-------. 1 devalone devalone 44 7月   8 14:44 temp.msMokc
    -rw-------. 1 devalone devalone 46 7月   8 14:44 temp.NKKmb6Tf

    [devalone@devalone dir.lk5PBB]$ cat temp.msMokc
    This is a test line of data for temp.msMokc

    [devalone@devalone dir.lk5PBB]$ cat temp.NKKmb6Tf
    This is a test line of data for temp.NKKmb6Tf

这段脚本在当前目录创建了一个目录,然后它用 cd 命令进入该目录,并创建了两个临时文件。之后这两个临时文件被分配给文件描述符,用来存储脚本的
输出。


5.8 记录消息
-----------------------------------------------------------------------------------------------------------------------------------------
将输出同时发送到显示器和日志文件,这种做法有时候能够派上用场。不用将输出重定向两次,只要用特殊的 tee 命令就行。

tee 命令相当于管道的一个 T 型接头。它将从 STDIN 过来的数据同时发往两处。一处是 STDOUT,另一处是 tee 命令行所指定的文件名:

    tee filename

由于 tee 会重定向来自 STDIN 的数据,可以用它配合管道命令来重定向命令输出。

示例:
    [devalone@devalone 15]$ date | tee testfile
    2018年 07月 08日 星期日 14:53:25 CST
    [devalone@devalone 15]$ cat testfile
    2018年 07月 08日 星期日 14:53:25 CST

输出出现在了 STDOUT 中,同时也写入了指定的文件中。注意,默认情况下,tee命令会在每次使用时覆盖输出文件内容。

示例:
    [devalone@devalone 15]$ who | tee testfile
    devalone pts/0        2018-07-08 12:12 (192.168.1.101)
    [devalone@devalone 15]$ cat testfile
    devalone pts/0        2018-07-08 12:12 (192.168.1.101)

如果想将数据追加到文件中,必须用 -a 选项。

示例:
    [devalone@devalone 15]$ date | tee -a testfile
    2018年 07月 08日 星期日 14:56:46 CST
    
    [devalone@devalone 15]$ cat testfile
    devalone pts/0        2018-07-08 12:12 (192.168.1.101)
    2018年 07月 08日 星期日 14:56:46 CST

利用这个方法,既能将数据保存在文件中,也能将数据显示在屏幕上。

示例:
    [devalone@devalone 15]$ 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

运行:
    [devalone@devalone 15]$ test22.sh
    This is the start of the test
    This is the second line of the test
    This is the end of the test

    [devalone@devalone 15]$ cat test22file
    This is the start of the test
    This is the second line of the test
    This is the end of the test

 

5.9 实例
-----------------------------------------------------------------------------------------------------------------------------------------
文件重定向常见于脚本需要读入文件和输出文件时。这个示例脚本两件事都做了。它读取 .csv 格式的数据文件,输出 SQL INSERT 语句来将数据插入数据库

shell 脚本使用命令行参数指定待读取的 .csv文件。.csv格式用于从电子表格中导出数据,所以可以把数据库数据放入电子表格中,把电子表格保存成.csv
格式,读取文件,然后创建 INSERT 语句将数据插入 MySQL 数据库。

代码:
    [devalone@devalone 15]$ 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}

这个脚本很短小,这都要感谢有了文件重定向!脚本中出现了三处重定向操作。while 循环使用 read语句从数据文件中读取文本。注意在 done 语句中出现
的重定向符号:

    done < ${1}

当运行程序 test23.sh 时,$1 代表第一个命令行参数。它指明了待读取数据的文件。read 语句会使用 IFS 字符解析读入的文本,我们在这里将 IFS 指定
为逗号。

脚本中另外两处重定向操作出现在同一条语句中:

    cat >> $outfile << EOF

这条语句中包含一个输出追加重定向(双大于号)和一个输入追加重定向(双小于号)。输出重定向将 cat 命令的输出追加到由 $outfile 变量指定的文件
中。cat 命令的输入不再取自标准输入,而是被重定向到脚本中存储的数据。EOF 符号标记了追加到文件中的数据的起止。

    INSERT INTO members (lname,fname,address,city,state,zip) VALUES
    ('$lname', '$fname', '$address', '$city', '$state', '$zip');

上面的文本生成了一个标准的 SQL INSERT语句。注意,其中的数据会由变量来替换,变量中内容则是由 read 语句存入的。

所以基本上 while 循环一次读取一行数据,将这些值放入 INSERT 语句模板中,然后将结果输出到输出文件中。

使用以下输入数据文件:

    [devalone@devalone 15]$ 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

运行脚本时,显示器上不会出现任何输出:

    [devalone@devalone 15]$ test23.sh members.csv
    [devalone@devalone 15]$

但是在members.sql输出文件中,会看到如下输出内容:

    [devalone@devalone 15]$ 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 ');

现在可以将 members.sql 文件导入 MySQL 数据表中。

 

 

系列目录:

    Linux shell 脚本编程-基础篇 (一)

    Linux shell 脚本编程-基础篇 (二)

    Linux shell 脚本编程-基础篇 (三)

    Linux shell 脚本编程-基础篇 (四)

    Linux shell 脚本编程-基础篇 (五)

    Linux shell 脚本编程-基础篇 (六)

 

-----------------------------------------------------------------------------------------------------------------------------------------

参考:

    《Linux 命令行与 shell 脚本编程大全》 第 3 版 —— 2016.8(美)Richard Blum  Cristine Bresnahan

Shell编程基础篇-上 1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell脚本语言,并能够阅 读系统及各类软件附带的Shell脚本内容。只有这样才能提升运维人员的工作效率,适 应曰益 阅读详情

相关推荐

Shell脚本编程基础及实战

本文还有配套的精品资源,点击获取 简介:标题和简介未提供具体信息,但通过标签“Shell”推测主题与Unix/Linux系统中的Shell脚本编程相关。Shell是命令行解释器,允许执行系统操作。Shell脚本用于自动化命令行任务,包含控制结构、条件语句、循环语句等。本课程深入探讨Shell编程基础,包括脚本结构、变量赋值、命令行参数处理、流程控制、文件与目录操作、管道与重...

weixin_42613017的博客 1558

Linux命令详解之 cat

linux 命令详解 命令名称: cat ( concatenate )连接文件并打印到标准输出 命令用法: cat [选项]... [文件]... 命令概述: 连接多个文件到标准输出。 如果没有文件,或则文件为 - ,则从标准输入读取数据。 命令参数: -A , --show-all : 显示全部 相当于 -vET,即将 -v -E -T 等参数同时用上 -b , --number-nonblank : 显示非空行的行号 给非空行标号,与 -n 相反 -e 相当于 -vE ,

Super辉sir的博客 4818

深入探讨 VQ-VAE:理解变分量化自动编码器

VQ-VAE代表"Variational Quantized Variational Autoencoder",是一种生成模型,通常用于处理高维数据,如图像和音频。它的设计灵感来自于变分自动编码器(VAE)和量化方法,结合了它们的优点,使得 VQ-VAE 能够生成高质量的数据,并在数据表示上引入离散性。VQ-VAE 是一种强大的生成模型,结合了变分自动编码器和量化方法的优点。它在图像和音频生成、数据压缩和生成性对抗网络等领域具有广泛的应用。

DeepViewInsight的博客 7016

linux循环读取文件内容放入变量,使用while 循环 用read 读取文件内容,直到文件尾部...

使用while循环一次读取文件的一行,直到文件尾部格式如下:whilereadline;do\\line为一个变量,表示读取到一行的字符循环体done使用read由标准输入读取数据,放入变量line中,如果读到的数据非空,就进入循环。示例:取得/etc/passwd的用户名及shell#!/bin/bash#IFS=':'##改变字段分隔符whilereadf1f2...

weixin_42525211的博客 2448

ZEMAX学习第7天-手机镜头光学系统设计全过程案例

接下来对系统微调,依次缩小CRA和畸变,首先对CRA进行依次递减(39°、38°、37°、36°、35°),目前CRA角度40度,每次下降一度进行优化,利用MAXX加OPLT一起控制,控制小于35°。可以看出在标注的三个地方镜头曲率变化,导致PY=1的光线走向奇特,因此需要对矢高进行调整,按照标注的地方依次调整(从右到左)至传函变好,越靠近右边对其余视场影响越小。3.圆锥系数值较大,透镜形状怪异;一、第1,3镜子偏厚,第4镜子偏薄,45镜子间隔边缘偏小,第5片镜子中心厚度与边缘厚度相差较大,需要控制;

liningliwei的博客 1085

深入解析MTK平台hang_detect机制:从原理到实战调试

本文深入解析了MTK平台hang_detect机制的工作原理与实战调试技巧。作为系统健康监测的核心机制,hang_detect通过多层级监控体系检测应用层和内核层异常,结合Kernel_exception等日志信息快速定位问题。文章详细介绍了典型问题案例、调试方法及预防措施,帮助开发者提升MTK平台系统稳定性调试能力。

purple的博客 1005

linux shell及脚本编写,环境变量及重定向

一、 1、命令行编辑(emas风格和vi风格) ctrl+a (moves to beginning of line) ctrl+e (moves to end of line) ctrl+u(deletes to begining of line) ctrl+k(deletes to end of line) ctrl+<-或-> (一次移动...

weixin_33994444的博客 218

YOLOv11改进策略【Neck】| BiFPN:双向特征金字塔网络-跨尺度连接和加权特征融合

可扩展的高效物体检测BiFPN(加权双向特征金字塔网络)

Limiiiing的博客 5499

linux--exec命令

shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。   因此,如果你在一个shell里面,执行exec ls;那么,当列出了当前目录后,这个shell就自己退出了,因为这个shell进程已被替换为仅仅执行ls命令的一个进程,执行结束自然也就退出了。为了避免这个影响我们的使用,一般将exec命令放到一个shell脚本里面,用主脚本调用这个脚本,调用点处可以用bash a.sh,(a.sh就是存放

daobuxinzi的博客 5140

初学者入门YOLO目标检测:从懵圈到上手,这篇文章讲透所有核心(附学习路径+避坑指南)

目标:比如训练一个“检测苹果和橘子”的模型,或者“检测人脸”的模型;任务:学会用LabelImg标注数据,制作YOLO格式的数据集,用命令行训练模型;关键:不用追求高精度,能训练出一个能检测出目标的模型就行。很多初学者卡在入门阶段,不是因为智商不够,而是因为“想太多,做太少”——总觉得要把所有原理搞懂才能动手,结果越想越怕,最后放弃。先动手,再动脑。先跑通一个案例,获得成就感;再制作自定义数据集,训练简单模型;最后再回头去理解原理,优化模型。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 691

海康visionmaster开发笔记10-集成HALCON第三方算子到VM工具箱的方法

海康visionmaster开发笔记10-HALCON第三方算子到VM工具箱的方法

视觉人机器视觉的博客 4349

Linux shell 脚本编程-高级篇 (五)

继: Linux shell 脚本编程-高级篇 (四) 5. sed 进阶 sed 编辑器的基础命令能满足大多数日常文本编辑需求。本节介绍 sed 编辑器提供的更多高级特性。这些功能未必会经常用到,但当需要时,知道这些功能 的存在以及如何使用它们是必要的。 5.1 多行命令 ---------------------------------------------------------...

devalone 的专栏 922

基于 YOLOv26 的校园安全监控系统:多场景应用

本文提出了一种基于YOLOv26的校园安全监控系统,采用多场景应用架构实现对校园安全的智能监测。系统核心技术包括YOLOv26目标检测、DeepSORT目标跟踪、区域安全定义和行为分析等模块,通过边缘计算平台实现实时处理。研究构建了包含多种校园场景的专业数据集,并采用数据增强技术提升模型性能。系统可检测人员、车辆和物品等目标,分析其行为轨迹,评估安全风险并触发告警。实验结果表明,该系统能有效识别校园安全隐患,为安全管理提供智能化解决方案。

一键难忘的博客 506

嵌入式 Linux 入门(五、Shell 脚本编程上:认识 Shell 脚本)

嵌入式 Linux入 门第五课,本课开始学习一下 Shell 脚本编程,我们从认识 Shell 脚本开始。

不浮夸,不将就,认真对待学知识的我们 4604

支持UE4.27、UE5.0、UE5.1、UE5.2、UE5.3、UE5.4、UE5.5的VS2022一键安装方法

本文提供了两种安装VS2022以支持UE5开发的方案。方案一通过百度网盘提供一键安装包,下载解压后以管理员身份运行批处理文件即可完成安装。方案二需从微软官网下载安装程序,通过创建包含特定参数的批处理文件来自定义安装组件。两种方案都需保持联网环境,建议先卸载旧版VS。安装完成后可测试打包UEC++项目Windows包。

2501_93651177的博客 356

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Linux Shell 脚本编程基础知识篇—shell简介以及基本操作

Shell本身是一个用C语言编写的程序, 它是用户使用Linux的桥梁。Shell既是一种命令语言, 又是一种程序设计语言。所有的Linux命令都是Shell脚本语言。

weixin_55767624的博客 2723

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

【Linux】基础篇四--shell脚本编程

Linux学习4--shell脚本编程一、shell编程-变量1、shell脚本的基础知识2、shell变量二、shell编程-功能语句1、说明性语句2、常用功能性语句3、测试语句三、shell编程-分支语句1、条件语句2、多路分支语句四、shell编程-循环语句1、循环语句for的用法2、循环语句while的用法3、循环控制语句五、shell编程-函数1、shell函数调用2、函数变量作用域 一、shell编程-变量 1、shell脚本的基础知识 (1)shell脚本的本质 程序语言包括编译型语言与解释型

修成真的博客 8168

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Linux基础命令-SHELL脚本编程基础

Linux基础命令-SHELL脚本编程基础SHELL脚本编程基础一、编程基础1. 编程基础2. 程序的执行方式3. 编译和解释型语言4. 编程基本概念二、脚本基本格式1. shell脚本基础2. 创建shell脚本3. 脚本规范4. 编程基本概念5. shell脚本示例6. 脚本调试三、变量1. 变量2. bash中变量的种类a. 局部变量b. 环境变量c. 只读和位置变量3. 退出状态4. 退出...

qq_41596208的博客 1604

Linux 编写shell 脚本基础篇

LInux shell编程基础 sh bash dash区别 执行脚本方式 变量的使用 字符串

xxx_un的博客 2271

Linux基础之shell脚本

shell脚本的本质就是 shell命令的有序集合 ,它属于一种解释型语言,不需要编译,方便操作者对重复性的劳动进行编程,同时shell脚本也是一种无类型语言,其变量没有类型或字符串类型注意事项: 对标点符号 和 格式 非常严格 特别是空格。

JIANG9720的博客 6703

Linux基础_SHELL脚本编程基础

讲师_@王晓春 本章内容▼编程基础▼shell脚本基础▷创建shell脚本▷脚本的基本结构▷变量1. Shell中变量命名法则:2. bash中变量的种类局部变量环境变量位置变量退出状态3. 算术运算赋值逻辑运算4. test命令bash的数值测试bash的文件测试54. 使用read命令来接受输入6. 条件选择 if 语句7. 条件判断:case语句▼bash的配置文件▷编辑配置文件生效1. B...

Not Found 404 3948

linux-Shell 编程-Shell 脚本基础

Shell脚本是由一系列Linux命令组成的文本文件,通常用于自动化完成任务。Shell脚本可以在终端中运行,而无需逐个输入命令。Shell脚本的扩展名通常为.sh,但这不是强制性的。在Shell脚本中,变量的使用是非常灵活的。变量名必须以字母或下划线开头,不能以数字开头。定义变量引用变量在引用变量时,需要在变量名前加上# 函数体Shell脚本是Linux系统管理中不可或缺的工具。通过Shell编程,用户可以自动化处理系统任务、文件操作、网络操作等一系列功能。

Flying_Fish_roe的博客 1698

SHELL 脚本编程基础

文章目录1. shell 概述1.1 shell 和 shell 脚本1.2 Shell 脚本应用场景1.4 shell 类型 1. shell 概述 1.1 shell 和 shell 脚本   shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务,在用户和内核之间充当翻译官的角色,是一个命令解释器。Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 shell。   shell 脚本(

shenyuanhaojie的博客 3万+

Linux Shell 脚本编程基础知识篇—shell 运算命令详解

各位好,我是练小杰,本文继续Linux shell脚本编程的基础知识内容,接着讲算术运算命令的详细操作,主要是led命令,read命令,be命令,expr命令等。

weixin_55767624的博客 1738

Linux之Shell脚本编程入门

Linux之Shell脚本编程入门,包括shell变量、运算符、条件判断、流程控制等语法案例

yuanjinshenglife的专栏 2341

Linux 之shell脚本编程

01 Linux 系统环境 文件系统结构 / 虚拟目录的根目录。通常不会在这里存储文件 /bin 二进制目录,存放许多用户级的GNU工具 /boot 启动目录,存放启动文件 /dev 设备目录,Linux在这里创建设备节点 /etc 系统配置文件目录 /home 主目录,Linux在这里创建用户目录 /lib 库目录,存放系统和应用程序的库文件 /media 媒体目录,可移动媒体设备的常用挂载点 /root root用户的主目录 /sbin 系统二进制目录,存放许多GNU管理员级工

wangprince2017 6219
上一篇: Linux shell 脚本编程-基础篇 (四)
下一篇: Linux shell 脚本编程-基础篇 (六)
devalone
博客等级 码龄17年 108粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值