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

Linux基础命令-SHELL脚本编程进阶 Linux基础命令-SHELL脚本编程进阶SHELL脚本编程进阶一、grep1. grep概念 SHELL脚本编程进阶 一、grep 1. grep概念 阅读详情

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

6. gawk 进阶


本节将进一步深入了解如何定制 gawk。gawk 是一门功能丰富的编程语言,可以通过它所提供的各种特性来编写高级程序处理数据。

 

6.1 使用变量


所有编程语言共有的一个重要特性是使用变量来存取值。gawk编程语言支持两种不同类型的变量:

    □ 内建变量
    □ 自定义变量

gawk 有一些内建变量。这些变量存放用来处理数据文件中的数据字段和记录的信息。用户也可以在 gawk 程序里创建自己的变量。


6.1.1 内建变量
-----------------------------------------------------------------------------------------------------------------------------------------

gawk 程序使用内建变量来引用程序数据里的一些特殊功能。


■ 字段和记录分隔符变量
-----------------------------------------------------------------------------------------------------------------------------------------
数据字段变量允许使用美元符号($)和字段在该记录中的位置值来引用记录对应的字段。要引用记录中的第一个数据字段,就用变量 $1;引用第二个字段,
就用 $2,依次类推。

数据字段是由字段分隔符来划定的。默认情况下,字段分隔符是一个空白字符,也就是空格符或者制表符。在命令行下使用命令行参数 -F 或者在 gawk 程序
中使用特殊的内建变量 FS 来更改字段分隔符。

内建变量 FS 是一组内建变量中的一个,这组变量用于控制 gawk 如何处理输入输出数据中的字段和记录。下表列出了这些内建变量:

    gawk 数据字段和记录变量
    +---------------+-------------------------------------------------------------------------
    | 变 量            | 描 述
    +---------------+-------------------------------------------------------------------------
    | FIELDWIDTHS    | 由空格分隔的一列数字,定义了每个数据字段确切宽度
    +---------------+-------------------------------------------------------------------------
    | FS            | 输入字段分隔符
    +---------------+-------------------------------------------------------------------------
    | RS            | 输入记录分隔符
    +---------------+-------------------------------------------------------------------------
    | OFS            | 输出字段分隔符
    +---------------+-------------------------------------------------------------------------
    | ORS            | 输出记录分隔符
    +---------------+-------------------------------------------------------------------------

变量 FS 和 OFS 定义了 gawk 如何处理数据流中的数据字段。我们已经知道了如何使用变量 FS 来定义记录中的字段分隔符。变量 OFS 具备相同的功能,
只不过是用在 print 命令的输出上。

默认情况下,gawk 将 OFS 设成一个空格,所以如果用命令:

    print $1,$2,$3

会看到如下输出:

    field1 field2 field3
    
示例:
    [devalone@devalone 22]$ cat data1
    data11,data12,data13,data14,data15
    data21,data22,data23,data24,data25
    data31,data32,data33,data34,data35
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","} {print $1,$2,$3}' data1
    data11 data12 data13
    data21 data22 data23
    data31 data32 data33

print 命令会自动将 OFS 变量的值放置在输出中的每个字段间。通过设置 OFS 变量,可以在输出中使用任意字符串来分隔字段。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=",";OFS="-"} {print $1,$2,$3}' data1
    data11-data12-data13
    data21-data22-data23
    data31-data32-data33

    [devalone@devalone 22]$ gawk 'BEGIN{FS=",";OFS="--"} {print $1,$2,$3}' data1
    data11--data12--data13
    data21--data22--data23
    data31--data32--data33

    [devalone@devalone 22]$ gawk 'BEGIN{FS=",";OFS="<-->"} {print $1,$2,$3}' data1
    data11<-->data12<-->data13
    data21<-->data22<-->data23
    data31<-->data32<-->data33

FIELDWIDTHS 变量允许不依靠字段分隔符来读取记录。在一些应用程序中,数据并没有使用字段分隔符,而是被放置在了记录中的特定列。这种情况下,必须
设定 FIELDWIDTHS 变量来匹配数据在记录中的位置。

一旦设置了 FIELDWIDTH 变量,gawk 就会忽略 FS 变量,并根据提供的字段宽度来计算字段。下面是个采用字段宽度而非字段分隔符的例子:

    [devalone@devalone 22]$ cat data1b
    1005.3247596.37
    115-2.349194.00
    05810.1298100.1
    [devalone@devalone 22]$ gawk 'BEGIN{FIELDWIDTHS="3 5 2 5"}{print $1,$2,$3}' data1b
    100 5.324 75
    115 -2.34 91
    058 10.12 98

FIELDWIDTHS 变量定义了四个字段,gawk 依此来解析数据记录。每个记录中的数字串会根据已定义好的字段长度来分割。

    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    一定要记住,一旦设定了 FIELDWIDTHS 变量的值,就不能再改变了。这种方法并不适用于变长的字段。

变量 RS 和 ORS定义了 gawk程序如何处理数据流中的字段。默认情况下,gawk 将 RS 和 ORS 设为换行符。默认的 RS 值表明,输入数据流中的每行新文本
就是一条新纪录。

有时,会在数据流中碰到占据多行的字段。典型的例子是包含地址和电话号码的数据,其中地址和电话号码各占一行。

    Riley Mullen
    123 Main Street
    Chicago, IL 60601
    (312)555-1234

如果用默认的 FS 和 RS 变量值来读取这组数据,gawk 就会把每行作为一条单独的记录来读取,并将记录中的空格当作字段分隔符。这可不是希望看到的。

要解决这个问题,只需把 FS 变量设置成换行符。这就表明数据流中的每行都是一个单独的字段,每行上的所有数据都属于同一个字段。但现在令人头疼的
是无从判断一个新的数据行从何开始。

对于这一问题,可以把 RS 变量设置成空字符串,然后在数据记录间留一个空白行。gawk 会把每个空白行当作一个记录分隔符。

示例:
    [devalone@devalone 22]$ cat data2
    Riley Mullen
    123 Main Street
    Chicago, IL 60601
    (312)555-1234

    Frank Williams
    456 Oak Street
    Indianapolis, IN 46201
    (317)555-9876

    Haley Snell
    4231 Elm Street
    Detroit, MI 48201
    (313)555-4938
    [devalone@devalone 22]$ gawk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' data2
    Riley Mullen (312)555-1234
    Frank Williams (317)555-9876
    Haley Snell (313)555-4938

现在 gawk 把文件中的每行都当成一个字段,把空白行当作记录分隔符。


■ 数据变量
-----------------------------------------------------------------------------------------------------------------------------------------
除了字段和记录分隔符变量外,gawk 还提供了其他一些内建变量来帮助了解数据发生了什么变化,并提取 shell 环境的信息。下表列出了 gawk 中的其他
内建变量:

    更多的 gawk 内建变量
    +---------------+--------------------------------------------------------------------------
    | 变 量            | 描 述
    +---------------+--------------------------------------------------------------------------
    | ARGC            | 当前命令行参数个数
    +---------------+--------------------------------------------------------------------------
    | ARGIND        | 当前文件在ARGV中的位置
    +---------------+--------------------------------------------------------------------------
    | ARGV            | 包含命令行参数的数组
    +---------------+--------------------------------------------------------------------------
    | CONVFMT        | 数字的转换格式(参见printf语句),默认值为%.6 g
    +---------------+--------------------------------------------------------------------------
    | ENVIRON        | 当前shell环境变量及其值组成的关联数组
    +---------------+--------------------------------------------------------------------------
    | ERRNO            | 当读取或关闭输入文件发生错误时的系统错误号
    +---------------+--------------------------------------------------------------------------
    | FILENAME        | 用作gawk输入数据的数据文件的文件名
    +---------------+--------------------------------------------------------------------------
    | FNR            | 当前数据文件中的数据行数
    +---------------+--------------------------------------------------------------------------
    | IGNORECASE    | 设成非零值时,忽略gawk命令中出现的字符串的字符大小写
    +---------------+--------------------------------------------------------------------------
    | NF            | 数据记录中的字段总数
    +---------------+--------------------------------------------------------------------------
    | NR            | 已处理的输入记录数
    +---------------+--------------------------------------------------------------------------
    | OFMT            | 数字的输出格式,默认值为%.6 g
    +---------------+--------------------------------------------------------------------------
    | RLENGTH        | 由 match 函数所匹配的子字符串的长度
    +---------------+--------------------------------------------------------------------------
    | RSTART        | 由 match 函数所匹配的子字符串的起始位置
    +---------------+--------------------------------------------------------------------------


ARGC 和 ARGV 变量允许从 shell 中获得命令行参数的总数以及它们的值。但这可能有点麻烦,因为 gawk 并不会将程序脚本当成命令行参数的一部分。

如:
    [devalone@devalone 22]$ gawk 'BEGIN{print ARGC,ARGV[0]}' data1
    2 gawk
    [devalone@devalone 22]$ gawk 'BEGIN{print ARGC,ARGV[1]}' data1
    2 data1

ARGC 变量表明命令行上有两个参数。这包括 gawk 命令和 data1参 数(记住,程序脚本并不算参数)。ARGV 数组从索引 0 开始,代表的是命令。第一个
数组值是 gawk 命令后的第一个命令行参数。


    NOTE:
    -------------------------------------------------------------------------------------------------------------------------------------
    跟 shell 变量不同,在脚本中引用 gawk 变量时,变量名前不加美元符。

ENVIRON 变量使用关联数组来提取 shell 环境变量。关联数组用文本作为数组的索引值,而不是数值。

数组索引中的文本是 shell 环境变量名,而数组的值则是 shell 环境变量的值。

示例:
    [devalone@devalone 22]$ gawk '
    > BEGIN{
    > print ENVIRON["HOME"]
    > print ENVIRON["PATH"]
    > }'
    /home/devalone
    /usr/local/protoc/bin:/home/devalone/programs/apache-tomcat-8.5.11/bin:/usr/local/apache/maven/bin:/usr/local/apache/ant/bin

ENVIRON["HOME"] 变量从 shell 中提取了 HOME 环境变量的值。类似地,ENVIRON["PATH"] 提取了 PATH 环境变量的值。可以用这种方法来从 shell 中
提取任何环境变量的值,以供 gawk 程序使用。

当要在 gawk 程序中跟踪数据字段和记录时,变量 FNR、NF 和 NR 用起来就非常方便。有时并不知道记录中到底有多少个数据字段。NF 变量可以在不知道
具体位置的情况下指定记录中的最后一个数据字段。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=":";OFS=":"} {print $1, $NF}' /etc/passwd
    root:/bin/bash
    bin:/sbin/nologin
    daemon:/sbin/nologin
    adm:/sbin/nologin
    lp:/sbin/nologin
    sync:/bin/sync
    shutdown:/sbin/shutdown
    
    ...
    devalone:/bin/bash

NF 变量含有数据记录中最后一个数据字段的数字值。可以在它前面加个美元符将其用作字段变量。

FNR 和 NR 变量虽然类似,但又略有不同。FNR 变量含有当前数据文件中已处理过的记录数,NR 变量则含有已处理过的记录总数。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","}{print $1, "FNR="FNR}' data1 data1
    data11 FNR=1
    data21 FNR=2
    data31 FNR=3
    data11 FNR=1
    data21 FNR=2
    data31 FNR=3

在这个例子中,gawk 程序的命令行定义了两个输入文件(两次指定的是同样的输入文件)。这个脚本会打印第一个数据字段的值和 FNR 变量的当前值。
注意,当 gawk 程序处理第二个数据文件时,FNR 值被设回了 1。

现在,加上 NR 变量看看会输出什么:

    [devalone@devalone 22]$ gawk 'BEGIN{FS=","}{print $1, "FNR="FNR,"NR="NR} END{print "There were",NR, "records processed"}' data1 data1
    data11 FNR=1 NR=1
    data21 FNR=2 NR=2
    data31 FNR=3 NR=3
    data11 FNR=1 NR=4
    data21 FNR=2 NR=5
    data31 FNR=3 NR=6
    There were 6 records processed

FNR 变量的值在 gawk 处理第二个数据文件时被重置了,而 NR 变量则在处理第二个数据文件时继续计数。结果就是:如果只使用一个数据文件作为输入,
FNR 和 NR的值是相同的;如果使用多个数据文件作为输入,FNR 的值会在处理每个数据文件时被重置,而 NR 的值则会继续计数直到处理完所有的数据文件。


6.1.2 自定义变量
-----------------------------------------------------------------------------------------------------------------------------------------
跟其他典型的编程语言一样,gawk 允许用户定义自己的变量在程序代码中使用。gawk 自定义变量名可以是任意数目的字母、数字和下划线,但不能以数字
开头。gawk 变量名区分大小写。


■ 在脚本中给变量赋值
-----------------------------------------------------------------------------------------------------------------------------------------
在 gawk 程序中给变量赋值跟在 shell 脚本中赋值类似,都用赋值语句:

    [devalone@devalone 22]$ gawk '
    > BEGIN{
    > testing="This is a test"
    > print testing
    > }'
    This is a test

print 语句的输出是 testing 变量的当前值。跟 shell 脚本变量一样,gawk 变量可以保存数值或文本值。

示例:
    [devalone@devalone 22]$ gawk '
    > BEGIN{
    > testing="this is a test"
    > print testing
    > testing=45
    > print testing
    > }'
    this is a test
    45

在这个例子中,testing 变量的值从文本值变成了数值。

赋值语句还可以包含数学算式来处理数字值:

    [devalone@devalone 22]$ gawk 'BEGIN {x=4;x=x * 2 + 3; print x}'
    11

gawk 编程语言包含了用来处理数字值的标准算数操作符。其中包括求余符号(%)和幂运算符号(^或**)。


■ 在命令行上给变量赋值
-----------------------------------------------------------------------------------------------------------------------------------------
也可以用 gawk 命令行来给程序中的变量赋值。这允许在正常的代码之外赋值,即时改变变量的值。下面的例子使用命令行变量来显示文件中特定数据字段。

示例:
    [devalone@devalone 22]$ cat script1.gawk
    BEGIN{FS=","}
    {print $n}
    [devalone@devalone 22]$ gawk -f script1.gawk n=2 data1
    data12
    data22
    data32
    [devalone@devalone 22]$ gawk -f script1.gawk n=3 data1
    data13
    data23
    data33

这个特性可以在不改变脚本代码的情况下就能够改变脚本的行为。第一个例子显示了文件的第二个数据字段,第二个例子显示了第三个数据字段,只要在命令
行上设置 n 变量的值就行。

使用命令行参数来定义变量值会有一个问题。在设置了变量后,这个值在代码的 BEGIN 部分不可用。

示例:
    [devalone@devalone 22]$ cat script2.gawk
    BEGIN{print "The starting value is",n; FS=","}
    {print $n}
    [devalone@devalone 22]$ gawk -f script2.gawk n=3 data1
    The starting value is
    data13
    data23
    data33

可以用 -v 命令行参数来解决这个问题。它允许在 BEGIN 代码之前设定变量。在命令行上,-v 命令行参数必须放在脚本代码之前。

示例:
    [devalone@devalone 22]$ gawk -v n=3 -f script2.gawk data1
    The starting value is 3
    data13
    data23
    data33

现在在 BEGIN 代码部分中的变量 n 的值已经是命令行上设定的那个值了。


6.2 处理数组
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言使用关联数组提供数组功能。关联数组跟数字数组不同之处在于它的索引值可以是任意文本字符串。不需要用连续的数字来标识数组中的数据
元素。相反,关联数组用各种字符串来引用值。每个索引字符串都必须能够唯一地标识出赋给它的数据元素。


6.2.1 定义数组变量
-----------------------------------------------------------------------------------------------------------------------------------------
可以用标准赋值语句来定义数组变量。数组变量赋值的格式如下:

    var[index] = element
    
其中 var 是变量名,index 是关联数组的索引值,element 是数据元素值。下面是一些 gawk 中数组变量的例子:

    capital["Illinois"] = "Springfield"
    capital["Indiana"] = "Indianapolis"
    capital["Ohio"] = "Columbus"

在引用数组变量时,必须包含索引值来提取相应的数据元素值。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > capital["Illinois"] = "Springfield"
    > print capital["Illinois"]
    > }'
    Springfield

在引用数组变量时,会得到数据元素的值。数据元素值是数字值时也一样。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > var[1] = 34
    > var[2] = 3
    > total = var[1] + var[2]
    > print total
    > }'
    37

可以像使用 gawk 程序中的其他变量一样使用数组变量。


6.2.2 遍历数组变量
-----------------------------------------------------------------------------------------------------------------------------------------
关联数组变量的问题在于可能无法知晓索引值是什么。跟使用连续数字作为索引值的数字数组不同,关联数组的索引可以是任何东西。

如果要在 gawk 中遍历一个关联数组,可以用 for 语句的一种特殊形式:

    for (var in array)
    {
        statements
    }

这个 for 语句会在每次循环时将关联数组 array 的下一个索引值赋给变量 var,然后执行一遍 statements。重要的是记住这个变量中存储的是索引值而
不是数组元素值。可以将这个变量用作数组的索引,轻松地取出数据元素值。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > var["a"] = 1
    > var["b"] = 2
    > var["m"] = 3
    > var["u"] = 4
    > for (test in var)
    > {
    >     print "Index:", test, " - Value:", var[test]
    > }
    > }'
    Index: u  - Value: 4
    Index: m  - Value: 3
    Index: a  - Value: 1
    Index: b  - Value: 2

注意,索引值不会按任何特定顺序返回,但它们都能够指向对应的数据元素值。明白这点很重要,因为不能指望返回的值都是有固定的顺序,只能保证索引值
和数据值是对应的。


6.2.3 删除数组变量
-----------------------------------------------------------------------------------------------------------------------------------------
从关联数组中删除数组索引要用一个特殊的命令:

    delete array[index]

删除命令会从数组中删除关联索引值和相关的数据元素值。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > var["a"] = 1
    > var["g"] = 2
    > for (test in var)
    > {
    >     print "Index:", test, " - Value:", var[test]
    > }
    > delete var["g"]
    > print "---"
    > for (test in var)
    > {
    >     print "Index:", test, " - Value:", var[test]
    > }
    > }'
    Index: a  - Value: 1
    Index: g  - Value: 2
    ---
    Index: a  - Value: 1

一旦从关联数组中删除了索引值,就没法再用它来提取元素值。


6.3 使用模式
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 程序支持多种类型的匹配模式来过滤数据记录,这一点跟 sed 编辑器大同小异。之前已经介绍了两种特殊的模式在实践中的应用。BEGIN 和 END 关键
字是用来在读取数据流之前或之后执行命令的特殊模式。类似地,也可以创建其他模式在数据流中出现匹配数据时执行一些命令。


6.3.1 正则表达式
-----------------------------------------------------------------------------------------------------------------------------------------
可以用基础正则表达式(BRE)或扩展正则表达式(ERE)来选择程序脚本作用在数据流中的哪些行上。

在使用正则表达式时,正则表达式必须出现在它要控制的程序脚本的左花括号前。

示例:
    [devalone@devalone 22]$ cat data1
    data11,data12,data13,data14,data15
    data21,data22,data23,data24,data25
    data31,data32,data33,data34,data35
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","} /11/{print $1}' data1
    data11


正则表达式 /11/ 匹配了数据字段中含有字符串11的记录。gawk 程序会用正则表达式对记录中所有的数据字段进行匹配,包括字段分隔符。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","} /,d/{print $1}' data1
    data11
    data21
    data31

这个例子使用正则表达式匹配了用作字段分隔符的逗号。这也并不总是件好事。它可能会造成如下问题:当试图匹配某个数据字段中的特定数据时,这些
数据又出现在其他数据字段中。如果需要用正则表达式匹配某个特定的数据实例,应该使用匹配操作符。


6.3.2 匹配操作符
-----------------------------------------------------------------------------------------------------------------------------------------
匹配操作符(matching operator)允许将正则表达式限定在记录中的特定数据字段。匹配操作符是波浪线(~)。可以指定匹配操作符、数据字段变量以及
要匹配的正则表达式,如:

    $1 ~ /^data/

$1 变量代表记录中的第一个数据字段。这个表达式会过滤出第一个字段以文本 data 开头的所有记录。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1
    data21,data22,data23,data24,data25

匹配操作符会用正则表达式 /^data2/ 来比较第二个数据字段,该正则表达式指明字符串要以文本 data2 开头。

这是件强大的工具,gawk 程序脚本中经常用它在数据文件中搜索特定的数据元素。

示例:
    [devalone@devalone 22]$ gawk -F: '$1 ~ /devalone/{print $1, $NF}' /etc/passwd
    devalone /bin/bash

这个例子会在第一个数据字段中查找文本 devalon。如果在记录中找到了这个模式,它会打印该记录的第一个和最后一个数据字段值。

也可以用 ! 符号来排除正则表达式的匹配:

    $1 !~ /expression/
    
如果记录中没有找到匹配正则表达式的文本,程序脚本就会作用到记录数据。

示例:
    [devalone@devalone 22]$ gawk -F: '$1 !~ /devalone/{print $1, $NF}' /etc/passwd
    root /bin/bash
    bin /sbin/nologin
    daemon /sbin/nologin
    adm /sbin/nologin
    lp /sbin/nologin
    sync /bin/sync
    shutdown /sbin/shutdown
    halt /sbin/halt
    mail /sbin/nologin
    ...

这个例子中,gawk 程序脚本打印 /etc/passwd 文件中与用户ID devalone 不匹配的用户ID和登录 shell。


6.3.3 数学表达式
-----------------------------------------------------------------------------------------------------------------------------------------
除了正则表达式,也可以在匹配模式中用数学表达式。这个功能在匹配数据字段中的数字值时非常方便。

示例: 显示所有属于root用户组(组ID为0)的系统用户

    [devalone@devalone 22]$ gawk -F: '$4 == 0{print $1}' /etc/passwd
    root
    sync
    shutdown
    halt
    operator

这段脚本会查看第四个数据字段含有值 0 的记录。在这个 Linux 系统中,有五个用户账户属于 root 用户组。

可以使用任何常见的数学比较表达式:

    □ x == y:值x等于y。
    □ x <= y:值x小于等于y。
    □ x < y:值x小于y。
    □ x >= y:值x大于等于y。
    □ x > y:值x大于y。

也可以对文本数据使用表达式,但必须小心。跟正则表达式不同,表达式必须完全匹配。数据必须跟模式严格匹配。

示例:
    [devalone@devalone 22]$ gawk -F, '$1 == "data"{print $1}' data1
    [devalone@devalone 22]$
    [devalone@devalone 22]$ gawk -F, '$1 == "data11"{print $1}' data1
    data11
    [devalone@devalone 22]$

第一个测试没有匹配任何记录,因为第一个数据字段的值不在任何记录中。第二个测试用值 data11 匹配了一条记录。


6.4 结构化命令
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言支持常见的结构化编程命令。


6.4.1 if 语句
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言支持标准的 if-then-else 格式的 if 语句。必须为 if 语句定义一个求值的条件,并将其用圆括号括起来。如果条件求值为 TRUE,紧跟在
if 语句后的语句会执行。如果条件求值为 FALSE,这条语句就会被跳过。可以用这种格式:

    if (condition)
        statement1

也可以将它放在一行上,像这样:
    
    if (condition) statement1

示例:
    [devalone@devalone 22]$ gawk '{if ($1 > 20) print $1}' data4
    50
    34

如果需要在 if 语句中执行多条语句,就必须用花括号将它们括起来。

示例:
    [devalone@devalone 22]$ gawk '{
    > if ($1 > 20)
    > {
    >     x = $1 * 2
    >     print x
    > }
    > }' data4
    100
    68

注意,不能弄混 if 语句的花括号和用来表示程序脚本开始和结束的花括号。如果弄混了,gawk 程序能够发现丢失了花括号,并产生一条错误消息。

gawk 的 if 语句也支持 else 子句,允许在 if 语句条件不成立的情况下执行一条或多条语句。

示例:
    [devalone@devalone 22]$ gawk '{
    > if ($1 > 20)
    > {
    >     x = $1 * 2
    >     print x
    > } else
    > {
    >     x = $1 /2
    >     print x
    > }}' data4
    5
    2.5
    6.5
    100
    68

可以在单行上使用 else 子句,但必须在 if 语句部分之后使用分号:

    if (condition) statement1; else statement2
    
示例:
    [devalone@devalone 22]$ gawk '{if ($1 > 20) print $1 * 2; else print $1/2}' data4
    5
    2.5
    6.5
    100
    68

这个格式更紧凑,但也更难理解。


6.4.2 while 语句
-----------------------------------------------------------------------------------------------------------------------------------------
while 语句为 gawk 程序提供了一个基本的循环功能。下面是 while 语句的格式:

    while (condition)
    {
        statements
    }

while 循环允许遍历一组数据,并检查迭代的结束条件。如果在计算中必须使用每条记录中的多个数据值,这个功能能帮得上忙。

示例:
    [devalone@devalone 22]$ cat data5
    130 120 135
    160 113 140
    145 170 215
    [devalone@devalone 22]$ gawk '{
    > total = 0
    > i = 1
    > while (i < 4)
    > {
    >     total += $i
    >     i++
    > }
    > avg = total / 3
    > print "Average:",avg
    > }' data5
    Average: 128.333
    Average: 137.667
    Average: 176.667

while 语句会遍历记录中的数据字段,将每个值都加到 total 变量上,并将计数器变量 i 增值。当计数器值等于 4 时,while 的条件变成了 FALSE,循环
结束,然后执行脚本中的下一条语句。这条语句会计算并打印出平均值。这个过程会在数据文件中的每条记录上不断重复。

gawk 编程语言支持在 while 循环中使用 break 语句和 continue语句,允许从循环中跳出。

示例:
    [devalone@devalone 22]$ gawk '{
    > total = 0
    > i = 1
    > while (i < 4)
    > {
    >     total += $i
    >     if (i == 2)
    >         break
    >     i++
    > }
    > avg = total / 2
    > print "The average of the first two data elements is:",avg
    > }' data5
    The average of the first two data elements is: 125
    The average of the first two data elements is: 136.5
    The average of the first two data elements is: 157.5

 

6.4.3 do-while 语句
-----------------------------------------------------------------------------------------------------------------------------------------
do-while 语句类似于 while 语句,但会在检查条件语句之前执行命令。下面是 do-while 语句的格式:

    do
    {
        statements
    } while (condition)

这种格式保证了语句会在条件被求值之前至少执行一次。当需要在求值条件前执行语句时,这个特性非常方便。

示例:
    [devalone@devalone 22]$ gawk '{
    > total = 0
    > i = 1
    > do
    > {
    >     total += $i
    >     i++
    > } while (total < 150)
    > print total }' data5
    250
    160
    315

这个脚本会读取每条记录的数据字段并将它们加在一起,直到累加结果达到 150。如果第一个数据字段大于150(就像在第二条记录中看到的那样),则脚本
会保证在条件被求值前至少读取第一个数据字段的内容。


6.4.4 for 语句
-----------------------------------------------------------------------------------------------------------------------------------------
for 语句是许多编程语言执行循环的常见方法。gawk 编程语言支持 C 风格的 for 循环:

    for( variable assignment; condition; iteration process)

示例:
    [devalone@devalone 22]$ gawk '{
    > total = 0
    > for (i=0; i<4; i++)
    > {
    >     total += $i
    > }
    > avg = total / 3
    > print "Average:",avg
    > }' data5
    Average: 171.667
    Average: 191
    Average: 225

定义了 for 循环中的迭代计数器,就不用担心要像使用 while 语句一样自己负责给计数器增值了。


6.5 格式化打印
-----------------------------------------------------------------------------------------------------------------------------------------
print 语句在 gawk 如何显示数据上并未提供多少控制。能做的只是控制输出字段分隔符(OFS)。如果要创建详尽的报表,通常需要为数据选择特定的格式
和位置。

解决办法是使用格式化打印命令,叫作 printf。如果熟悉 C 语言编程的话,gawk 中的 printf 命令用法也是一样,允许指定具体如何显示数据的指令。

printf 命令的格式:

    printf "format string", var1, var2 . . .

format string 是格式化输出的关键。它会用文本元素和格式化指定符来具体指定如何呈现格式化输出。格式化指定符是一种特殊的代码,会指明显示什么
类型的变量以及如何显示。gawk 程序会将每个格式化指定符作为占位符,供命令中的变量使用。第一个格式化指定符对应列出的第一个变量,第二个对应第
二个变量,依此类推。

格式化指定符采用如下格式:

    %[modifier]control-letter
    
其中 control-letter 是一个单字符代码,用于指明显示什么类型的数据,而 modifier 则定义了可选的格式化特性。下表列出了可用在格式化指定符中的
控制字母。


    格式化指定符的控制字母
    +-----------+------------------------------------------------------------------------------
    | 控制字母    | 描 述
    +-----------+------------------------------------------------------------------------------
    | c            | 将一个数作为ASCII字符显示
    +-----------+------------------------------------------------------------------------------
    | d            | 显示一个整数值
    +-----------+------------------------------------------------------------------------------
    | i            | 显示一个整数值(跟d一样)
    +-----------+------------------------------------------------------------------------------
    | e            | 用科学计数法显示一个数
    +-----------+------------------------------------------------------------------------------
    | f            | 显示一个浮点值
    +-----------+------------------------------------------------------------------------------
    | g            | 用科学计数法或浮点数显示(选择较短的格式)
    +-----------+------------------------------------------------------------------------------
    | o            | 显示一个八进制值
    +-----------+------------------------------------------------------------------------------
    | s            | 显示一个文本字符串
    +-----------+------------------------------------------------------------------------------
    | x            | 显示一个十六进制值
    +-----------+------------------------------------------------------------------------------
    | X            | 显示一个十六进制值,但用大写字母A~F
    +-----------+------------------------------------------------------------------------------

因此,如果需要显示一个字符串变量,可以用格式化指定符 %s。如果需要显示一个整数值,可以用 %d或 %i(%d 是十进制数的 C风格显示方式)。如果要
用科学计数法显示很大的值,就用 %e 格式化指定符。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > x = 10 * 100
    > printf "The answer is: %e\n",x
    > }'
    The answer is: 1.000000e+03

除了控制字母外,还有 3 种修饰符可以用来进一步控制输出:

    □ width:指定了输出字段最小宽度的数字值。如果输出短于这个值,printf 会将文本右对齐,并用空格进行填充。如果输出比指定的宽度还要长,
             则按照实际的长度输出。
    □ prec:这是一个数字值,指定了浮点数中小数点后面位数,或者文本字符串中显示的最大字符数。
    □ -(减号):指明在向格式化空间中放入数据时采用左对齐而不是右对齐。

在使用 printf 语句时,可以完全控制输出样式。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS="\n"; RS=""} {print $1, $4}' data2
    Riley Mullen (312)555-1234
    Frank Williams (317)555-9876
    Haley Snell (313)555-4938

可以用 printf 命令来帮助格式化输出,使得输出信息看起来更美观:

    [devalone@devalone 22]$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%s %s\n", $1, $4}' data2
    Riley Mullen (312)555-1234
    Frank Williams (317)555-9876
    Haley Snell (313)555-4938

注意,需要在 printf 命令的末尾手动添加换行符来生成新行。没添加的话,printf 命令会继续在同一行打印后续输出。如果需要用几个单独的 printf
命令在同一行上打印多个输出,这就会非常有用。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{FS=","} {printf "%s ", $1} END{printf "\n"}' data1
    data11 data21 data31

每个 printf 的输出都会出现在同一行上。为了终止该行,END 部分打印了一个换行符。

下一步,用修饰符来格式化第一个字符串值:

    [devalone@devalone 22]$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%16s %s\n", $1, $4}' data2
        Riley Mullen (312)555-1234
      Frank Williams (317)555-9876
         Haley Snell (313)555-4938

通过添加一个值为 16 的修饰符,强制第一个字符串的输出宽度为 16 个字符。默认情况下,printf 命令使用右对齐来将数据放到格式化空间中。要改成
左对齐,只需给修饰符加一个减号即可:

    [devalone@devalone 22]$ gawk 'BEGIN{FS="\n"; RS=""} {printf "%-16s %s\n", $1, $4}' data2
    Riley Mullen     (312)555-1234
    Frank Williams   (317)555-9876
    Haley Snell      (313)555-4938

现在看起来专业多了!

printf 命令在处理浮点值时也非常方便。通过为变量指定一个格式,可以让输出看起来更统一。

示例:
    [devalone@devalone 22]$ gawk '{
    > total = 0
    > for (i = 1; i < 4; i++)
    > {
    >     total += $i
    > }
    > avg = total / 3
    > printf "Average: %5.1f\n",avg
    > }' data5
    Average: 128.3
    Average: 137.7
    Average: 176.7

可以使用 %5.1f 格式指定符来强制 printf 命令将浮点值近似到小数点后一位。

 

6.6 内建函数
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言提供了不少内置函数,可进行一些常见的数学、字符串以及时间函数运算。可以在 gawk 程序中利用这些函数来减少脚本中的编码工作。


6.6.1 数学函数
-----------------------------------------------------------------------------------------------------------------------------------------
下表列出了 gawk 中内建的数学函数。

    gawk 数学函数
    +---------------+---------------------------------------------------------------------
    | 函 数            | 描 述
    +---------------+---------------------------------------------------------------------
    | atan2(x, y)    | x/y的反正切,x和y以弧度为单位
    +---------------+---------------------------------------------------------------------
    | cos(x)        | x的余弦,x以弧度为单位
    +---------------+---------------------------------------------------------------------
    | exp(x)        | x的指数函数
    +---------------+---------------------------------------------------------------------
    | int(x)        | x的整数部分,取靠近零一侧的值
    +---------------+---------------------------------------------------------------------
    | log(x)        | x的自然对数
    +---------------+---------------------------------------------------------------------
    | rand()        | 比0大比1小的随机浮点值
    +---------------+---------------------------------------------------------------------
    | sin(x)        | x的正弦,x以弧度为单位
    +---------------+---------------------------------------------------------------------
    | sqrt(x)        | x的平方根
    +---------------+---------------------------------------------------------------------
    | srand(x)        | 为计算随机数指定一个种子值
    +---------------+---------------------------------------------------------------------

虽然数学函数的数量并不多,但 gawk 提供了标准数学运算中要用到的一些基本元素。int() 函数会生成一个值的整数部分,但它并不会四舍五入取近似值。
它的做法更像其他编程语言中的 floor 函数。它会生成该值和 0 之间最接近该值的整数。

这意味着int()函数在值为 5.6 时返回 5,在值为 -5.6 时则返回 -5。

rand() 函数非常适合创建随机数,但需要用点技巧才能得到有意义的值。rand() 函数会返回一个随机数,但这个随机数只在 0和 1之间(不包括0或1)。
要得到更大的数,就需要放大返回值。

产生较大整数随机数的常见方法是用 rand() 函数和 int() 函数创建一个算法。

示例:
    
    x = int(10 * rand())
    
这会返回一个 0~9(包括0和9)的随机整数值。只要为程序用上限值替换掉等式中的 10 就可以了。

在使用一些数学函数时要小心,因为 gawk 语言对于它能够处理的数值有一个限定区间。如果超出了这个区间,就会得到一条错误消息。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{x = exp(100); print x}'
    26881171418161356094253400435962903554686976
    [devalone@devalone 22]$ gawk 'BEGIN{x = exp(1000); print x}'
    gawk: cmd. line:1: warning: exp: argument 1000 is out of range
    inf

第一个例子会计算 e 的 100次幂,虽然数值很大,但尚在系统的区间内。第二个例子尝试计算e 的 1000 次幂,已经超出了系统的数值区间,所以就生成了
一条错误消息。

除了标准数学函数外,gawk 还支持一些按位操作数据的函数:

    □ and(v1, v2)    :执行值 v1和 v2的按位与运算。
    □ compl(val)    :执行val的补运算。
    □ lshift(val, count):将值 val左移 count位。
    □ or(v1, v2)    :执行值 v1和 v2的按位或运算。
    □ rshift(val, count):将值 val右移 count位。
    □ xor(v1, v2)    :执行值 v1和 v2的按位异或运算。
    

位操作函数在处理数据中的二进制值时非常有用。


6.6.2 字符串函数
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言还提供了一些可用来处理字符串值的函数:


    gawk 字符串函数
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | 函 数                    | 描 述                                                                                            |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | asort(s [,d])            | 将数组 s 按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外,如果指定了 d,    |
    |                        | 则排序后的数组会存储在数组 d 中。                                                                |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | asorti(s [,d])        | 将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来表明排序顺序。        |
    |                        | 另外如果指定了d,排序后的数组会存储在数组d中                                                    |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | gensub(r, s, h [, t])    | 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或G开头的字符串,    |
    |                        | 就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第 h处 r匹配的地方                        |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | gsub(r, s [,t])        | 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s    |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | index(s, t)            | 返回字符串t在字符串s中的索引值,如果没找到的话返回0                                            |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | length([s])            | 返回字符串s的长度;如果没有指定的话,返回$0的长度                                                |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | match(s, r [,a])        | 返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分    |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | split(s, a [,r])        | 将 s 用 FS 字符或正则表达式 r(如果指定了的话)分开放到数组 a 中。返回字段的总数                |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | sprintf(format,        | 用提供的 format和 variables返回一个类似于 printf输出的字符串                                    |
    | variables)            |                                                                                                |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | sub(r, s [,t])        | 在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配            |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | substr(s, i [,n])        | 返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回 s剩下的部分                    |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | tolower(s)            | 将 s中的所有字符转换成小写                                                                    |
    +-----------------------+-----------------------------------------------------------------------------------------------+
    | toupper(s)            | 将 s中的所有字符转换成大写                                                                    |
    +-----------------------+-----------------------------------------------------------------------------------------------+

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{x = "testing"; print toupper(x); print length(x) }'
    TESTING
    7

但一些字符串函数的用法相当复杂。asort 和 asorti 函数是新加入的 gawk函数,允许基于数据元素值(asort)或索引值(asorti)对数组变量进行排序。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > var["a"] = 1
    > var["g"] = 2
    > var["m"] = 3
    > var["u"] = 4
    > asort(var,test)
    > for(i in test)
    >     print "Index:", i," - value:",test[i]
    > }'
    Index: 1  - value: 1
    Index: 2  - value: 2
    Index: 3  - value: 3
    Index: 4  - value: 4

新数组 test 含有排序后的原数组的数据元素,但索引值现在变为表明正确顺序的数字值了。

split 函数是将数据字段放到数组中以供进一步处理的好办法。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{ FS=","} {
    > split($0,var)
    > print var[1], var[5]
    > }' data1
    data11 data15
    data21 data25
    data31 data35

新数组使用连续数字作为数组索引,从含有第一个数据字段的索引值 1 开始。


6.6.3 时间函数
-----------------------------------------------------------------------------------------------------------------------------------------
gawk 编程语言包含一些函数来帮助处理时间值,如下表所示:


    gawk 的时间函数
    +-------------------------------+---------------------------------------------------------------------------------
    | 函 数                            | 描 述
    +-------------------------------+---------------------------------------------------------------------------------
    | mktime(datespec)                | 将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值
    +-------------------------------+---------------------------------------------------------------------------------
    | strftime(format [,timestamp])    | 将当前时间的时间戳或timestamp(如果提供了的话)转化格式化日期(采用shell
    |                                | 函数date()的格式)
    +-------------------------------+---------------------------------------------------------------------------------
    | systime( )                    | 返回当前时间的时间戳
    +-------------------------------+---------------------------------------------------------------------------------

时间函数常用来处理日志文件,而日志文件则常含有需要进行比较的日期。通过将日期的文本表示形式转换成 epoch时间(自1970-01-01 00:00:00 UTC 到
现在的秒数),可以轻松地比较日期。

示例:
    [devalone@devalone 22]$ gawk 'BEGIN{
    > date = systime()
    > day = strftime("%A,%B %d,%Y",date)
    > print day
    > }'
    星期五,七月 13,2018

该例用 systime 函数从系统获取当前的 epoch 时间戳,然后用 strftime 函数将它转换成用户可读的格式,转换过程中使用了 shell 命令 date 的日期
格式化字符。


6.7 自定义函数
-----------------------------------------------------------------------------------------------------------------------------------------
除了 gawk 中的内建函数,还可以在 gawk 程序中创建自定义函数。


6.7.1 定义函数
-----------------------------------------------------------------------------------------------------------------------------------------
要定义自己的函数,必须用 function 关键字:

    function name([variables])
    {
        statements
    }

函数名必须能够唯一标识函数。可以在调用的 gawk 程序中传给这个函数一个或多个变量。

示例:
function printthird()
{
    print $3
}

这个函数会打印记录中的第三个数据字段。

函数还能用 return 语句返回值:

    return value

值可以是变量,或者是最终能计算出值的算式:

    function myrand(limit)
    {
        return int(limit * rand())
    }

可以将函数的返回值赋给gawk程序中的一个变量:

    x = myrand(100)

这个变量包含函数的返回值。

 

6.7.2 使用自定义函数
-----------------------------------------------------------------------------------------------------------------------------------------
在定义函数时,它必须出现在所有代码块之前(包括 BEGIN 代码块)。乍一看可能有点怪异,但它有助于将函数代码与 gawk 程序的其他部分分开。

示例:
    [devalone@devalone 22]$ gawk '
    > function myprint()
    > {
    >     printf "%-16s - %s\n", $1,$4
    > }
    > BEGIN{FS="\n"; RS=""}
    > {
    >     myprint()
    > }' data2
    Riley Mullen     - (312)555-1234
    Frank Williams   - (317)555-9876
    Haley Snell      - (313)555-4938

函数定义了 myprint() 函数,它会格式化记录中的第一个和第四个数据字段以供打印输出。gawk 程序然后用该函数显示出数据文件中的数据。

 

6.7.3 创建函数库
-----------------------------------------------------------------------------------------------------------------------------------------
每次使用函数都要重写一遍并不美妙。gawk 提供了一种途径来将多个函数放到一个库文件中,这样就能在所有的 gawk 程序中使用了。

首先,需要创建一个存储所有 gawk 函数的文件。

    [devalone@devalone 22]$ cat funclib
    function myprint()
    {
            printf "%-16s - %s\n", $1, $4
    }

    function myrand(limit)
    {
            return int(limit * rand())
    }

    function printthird()
    {
            print $3
    }

funclib 文件含有三个函数定义。

需要使用 -f 命令行参数来使用它们。很遗憾,不能将 -f 命令行参数和内联 gawk 脚本放到一起使用,不过可以在同一个命令行中使用多个 -f 参数。

因此,要使用库,只要创建一个含有 gawk 程序的文件,然后在命令行上同时指定库文件和程序文件就行了。

示例:
    [devalone@devalone 22]$ cat script4.gawk
    BEGIN{ FS="\n"; RS=""}
    {
            myprint()
    }
    [devalone@devalone 22]$ gawk -f funclib -f script4.gawk data2
    Riley Mullen     - (312)555-1234
    Frank Williams   - (317)555-9876
    Haley Snell      - (313)555-4938

要做的是当需要使用库中定义的函数时,将 funclib 文件加到 gawk 命令行上就可以了。

 

 

系列目录:

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

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

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

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

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

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

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

 

 

-----------------------------------------------------------------------------------------------------------------------------------------
参考:

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

 

Linux Shell脚本编程大全:入门到高级技巧 Linux Shell脚本是一种用于自动化常规任务的脚本语言。它允许用户通过编写一系列命令来控制Linux系统的行为。Shell脚本经常被系统管理员和开发人员用于软件部署、系统监控、任务调度等场景。理解Shell脚本的基本工作原理和结构对于任何在Linux环境下工作的IT专业人员来说,都是一个重要的技能点。变量的定义和赋值是编写脚本时的基础操作。它们为脚本提供了可操作的数据。函数是一组命令的集合,可以被重复调用执行。在Shell脚本中,函数的使用提高了代码的复用性和可维护性。 阅读详情

相关推荐

Linux大作业

这是自己做的Linux大作业,所以大家不用担心老师会发现

Shell高级练习脚本15个

目录1.sed的基本使用2.sed的高级使用3.awk的基本使用4.awk高级用法其他

kali_yao的博客 1583

linux/shell大作业

LINUX/UNIX Shell编程大作业 在Linux系统的/etc目录下有这样一个文件passwd,该文件里包含系统中所有用户信息的记录,记录里包含每个用户的如下信息:用户名、密码、用户ID、组ID、用户全名、用户主目录和用户登录所用的shell。请设计一个脚本(shell)程序能实现增加、删除、查找和显示特定用户信息的功能。你们可以通过创建一些UNIX/LINUX shell 脚本文件来满足以上需求。 可以用任意一个文本编辑器打开passwd文件,该文件里包含用冒号分隔开的字段组成的记录,如下所示: root:x:0:0:root:/root:/bin/bash zxj:x:500:500:zxj303:/home/zxj:/bin/bash . . . 在主Shell脚本文件里(必须以 menu 命名)要有一个多操作选项的菜单以便用户从中选择。在不同任务的中,这些操作能自动实现以下功能: 1、 在屏幕上显示当前所有用户的记录 2、 在屏幕上显示当前所有用户(经过格式化和排序的)的记录 3、 只在屏幕上显示用户名和用户ID 4、 只在屏幕上显示(经过格式化和排序的)用户名和用户ID 5、 查询并显示特定用户的记录 6、 往passwd文件里增加新的用户记录 7、 从passwd文件里删除某个用户记录 你可以使用UNIX/LINUX中一些比较简单的命令或命令组合来执行1、2、3、4、5的任务。对于任务6和7,你需要编写单独的Shell脚本文件(必须分别命名为add和delete)并且在你的主脚本menu文件中调用这些脚本文件。

linux四舍五入,Linux 用 awk 加減乘除、取整數、四捨五入

最近在用 bash 寫一支監控的時候用到了很多運算式,用 bash 還真的有點雞肋,但其實只是一個簡單的監控,所以也懶得用其他語言寫了。首先在 Linux 上要用加減乘除不外乎就是 bc$ echo "5 + 2" | bc7$ echo "5 * 2" | bc10但是 bc 的除法就會有小數點$ echo "43 / 0.6" | bc25.8取整數有時候只是要拿來比大小的話,小數點就很麻煩,...

weixin_39929138的博客 6484

易灵思Trion FPGA实战:5分钟搞定MIPI硬核配置(附Interface Designer避坑指南)

本文详细介绍了易灵思Trion FPGA中MIPI硬核的快速配置方法,通过Interface Designer工具实现从时钟配置到数据收发的全流程实战。特别针对初次接触Trion系列的设计师,提供了六个关键配置陷阱及解决方案,帮助开发者高效完成嵌入式视觉和高速数据传输项目。

eee77的博客 794

创意视觉项目实战:用ESP32-S3+OV5640构建智能图像流系统

本文详细介绍了如何使用ESP32-S3开发板与OV5640摄像头模块构建智能图像流系统。从硬件连接到软件配置,涵盖Arduino环境搭建、图像采集优化、WiFi视频流传输及外设集成,为开发者提供完整的实战指南,助力智能家居和机器人视觉项目开发。

tech5的博客 1294

Shell脚本高级命令

trap 常见命令 trap '触发指令' 信号 ///将执行自定义信号,不会执行原操作 trap '' 信号 //忽略信号操作 trap '-' 信号 // #恢复原信号的操作 trap -p // #列出自定义信号操作 trap finish EXIT // #当脚本退出时,执行finish函数1、索引数组使用整数作为索引来访问和操作数组元素,编号是从0开始递增,属于数值索引;

Devin0501的博客 2209

海天注塑机弘讯控制器Modbus数据采集实战指南

工业设备数据采集是MES系统、设备监控和工艺追溯的基础,其中注塑机联网是车间数字化的关键环节。Modbus协议作为工业通信的事实标准,以简单、开放、低成本的优势,成为海天注塑机弘讯控制器对外提供数据的主要方式。理解控制器型号与通信参数、捋清寄存器点位表与字节序规则,是稳定采集的前提。通过RS485串口或以太网轮询,可以实时获取产量、温度、压力、报警等关键数据,进而支撑OEE统计、质量追溯与异常监控。本文基于实战项目,以海天注塑机弘讯控制器为例,梳理从接线、参数配置到点位验证的完整流程,为现场工程师提供一套可

weixin_28733777的博客 908

linux shell高级脚本,Shell 脚本编程(高级篇)

高级篇一、处理用户输入1. 读取脚本参数Bash Shell 将命令行中传递给脚本的参数赋值给一组特殊的变量,叫做位置变量(positional parameters)。位置变量用 $number 的形式表示。如 $0 表示脚本文件的名称,$1 表示脚本收到的第一个参数,$2 表示第二个参数,以此类推,直到 $9 表示第九个参数。从第十个参数起,使用 ${number} 的形式。即第十个参数表示为...

weixin_29080033的博客 637

如何导入su_利用GIS快速生成SU场地模型

01|前言:进入2021年了,希望大家也是一个新的开始。告诫自己多写文章多更新,多读点书多旅行。然而元旦由于出去玩了4天,积累了一些事情要处理,一直没有时间好好写点东西。今天给大家带来的分享主题叫“利用GIS快速生成SU场地模型”。相关的视频方法其实B站上也有,但我相信视频很多人都不会看,我自己也是。直接给大家上操作流程。主要的操作步骤是【获取场地的矢量shp文件】—【导入ArcScen...

weixin_33806859的博客 9813

Glue)《Multi-omics single-cell data integration and regulatory inference with graph-linked embedding》

论文引入GLUE框架,通过知识引导图(guidance graph)显式建模跨层调控交互,桥接特征空间,实现准确、鲁棒、可扩展的整合。近年来,单细胞测序技术(如scATAC-seq用于染色质可及性、snmC-seq用于DNA甲基化、scRNA-seq用于转录组)允许同时探测多个组学层,揭示细胞异质性和调控机制。GLUE优于现有方法:桥接特征空间,避免信息丢失,支持多组学和调控推断。用于整合未配对的单细胞多组学数据(如scRNA-seq、scATAC-seq和snmC-seq),并同时进行调控交互推断。

m0_58293236的博客 1152

Shell脚本的 6 个高级用法,从零基础到精通,收藏这篇就够了!

为了让脚本输出更加清晰易读,可以使用ANSI颜色代码来强调重要信息、警告和错误。

Javachichi的博客 1453

【Bug已解决】Context window exceeded / Token limit reached — Claude Code 上下文窗口超限解决方案

Claude Code 长会话中报上下文窗口/Token 超限,本质是对话历史、文件内容、工具结果累积超过 200K 上限。文中给出 /clear、/compact、分批读大文件、限制工具输出、配置 autoCompact 等完整方案。

一键难忘的博客 6732

六、Linux的Shell脚本编程

第六章:shell编程 1.1 shell的概念介绍 1.1.1 命令解释器 Shell是命令解释器(command interpreter),是Unix操作系统的用户接口,程序从用户接口得到输入信息,shell将用户程序及其输入翻译成操作系统内核(kernel)能够识别的指令,并且操作系统内核执行完将返回的输出通过shell再呈现给用户,下图所示用户、shell和操作系统的关系: 一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的shell。 .

程序猿的博客 9798

FPGA/IC 秋招笔试/面试题总结

文章目录一、FPGA内部资源1. 什么是FPGA2.FPGA内部资源二、同步时钟、同步/异步电路1.同步时钟2.同步/异步电路三、同步复位/异步复位1.同步复位2. 异步复位3. 异步复位同步释放四、同步FIFO/异步FIFO1.同步FIFO2.异步FIFO五、FIFO最小深度计算1.FIFO最小深度2.示例分析六、逻辑电平1.TTL电平标准2.LVTTL电平标准3.CMOS电平标准4.LVCOMS电平标准5.RS2326.RS4857.ECL、PECL、LVPECL8.LVDS9.CML10.GTL11

Crazzy_M的博客 4万+

【教程4>第1章>第12节】通过Verilog读取txt格式数据进行测试并将结果导入到matlab

我们在verilog的testbench中,调用txt文件,将上述正弦样本数据作为测试激励输入到verilog模块中。通过这个方法,可以将一些较为复杂的数据导入到verilog中,进行FPGA数据处理模块的开发。即通过w方式打开一个新的txt文件,然后将verilog的输出保存到XY1.txt文件中。这个部分是txt文件的路径,实际使用时,修改为您自己的路径,或者将txt文件放在和我一样的路径中。这个是数据长度,matlab产生的txt多少长度,这个参数就修改为多少长度。这个txt就是保存这段数据的文件。

FPGA/MATLAB学习教程/源码/项目合作开发 1390

【Linux】Shell脚本学习总结篇

【Linux】Shell脚本学习总结篇shell学习分为下面3个部分: shell基本命令回顾 shell基本语法学习 awk/sed 工具学习 关于shell的介绍之类的在这里不做赘述!shell基本命令回顾1.1 最基础的常用命令(注:命令选项直接 man 查看,不做说明) 1.1.1 查看文件和目录的命令ls : 列出目录下的清单; cat: 连接显示文件内容 less/more: 分页显

John的博客 2万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

嵌入式 Linux 入门(六、Shell 脚本编程下:Shell 脚本语法)

嵌入式 Linux 入门第六课,继续完成 Shell 脚本学习,本文学习 Shell 脚本语法

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

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

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

weixin_55767624的博客 2723

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

如何在 Linux 中创建 Shell 脚本

你想在你的 Linux 系统中创建一个 Shell 脚本吗? 本指南将带您了解如何使用多个文本编辑器创建 shell 脚本、如何添加注释以及如何使用 Shell 变量。 但是在开始创建 shell 脚本之前,让我们了解 Linux 中的 Shell 脚本是什么。 什么是 Linux 中的 Shell 脚本? 那么,什么是 Shell 脚本? Shell Scripting 被定义为由 Linux 或 Unix shell 运行的开源程序。通过 shell 脚本,您可以编写由 shell 执行的命令

lyfwx的博客 1万+

Linux 高级 Shell 脚本编程:掌握 Shell 脚本精髓,提升工作效率

函数体高级 Shell 脚本编程是提升 Shell 脚本编程技能的关键。通过学习函数、数组、高级控制结构和脚本调试技巧,你可以编写更高效、更灵活和更易于维护的脚本。掌握这些技能可以帮助你更好地利用 Shell 脚本解决实际问题,提高工作效率。

weixin_39372311的博客 1138

Linux 之shell脚本编程

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

wangprince2017 6219

【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

【Linux】Shell脚本编程

Shell是Linux系统的用户界面,它提供用户与内核的一种交互方式。它接收用户输入的命令,并把它送入内核去执行,是一个命令解释器Shell 既是一种命令语言,又是一种程序设计语言(Shell脚本)。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。Shell脚本就是将命令写入文本中,文本可以被执行。

ZLin0007的博客 2837

linux入门六:Linux Shell 编程

Shell 是 Linux 系统中用户与内核之间的桥梁,作为命令解析器,它负责将用户输入的文本命令转换为计算机可执行的机器指令。本质:Shell 是一个程序(如常见的 Bash、Zsh),而 Shell 脚本则是包含一系列命令的文本文件,通常以.sh结尾(非强制,仅为识别方便)。作用:批量执行重复命令、实现自动化任务、编写复杂逻辑程序。变量赋值空格a = 10错误,必须为a=10。中括号空格[条件]需写成[ 条件 ](如路径问题:执行脚本需用./脚本名,直接输入脚本名会提示 “命令未找到”。

嵌入式中手 1918

Linux之Shell脚本编程入门

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

yuanjinshenglife的专栏 2341
上一篇: 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、付费专栏及课程。

余额充值