当前位置: 首页 > news >正文

Shell脚本编程3(函数+正则表达式)

1.函数

1.1 定义

简单来讲,所谓函数就是把完成特定功能,并且多次使用的一组命令或者语句封装在一个固定的结构中,这个结构我们就叫做函数。从本质上讲,函数是将一个函数名与某个代码块进行映射。也就是说,用户在定义了函数之后,就可以通过函数名来调用其所对应的一组代码。
使用shell函数优势
    1、把相同的程序段定义为函数,可以减少整个程序段代码量,提升开发效率。
    2、增加程序段可读性、易读性,提升管理效率。
    3、可以实现程序功能模块化,使得程序具备通用性(可移植性)。

1.2 语法

function 函数名() {指令return
}
简化写法1:
function 函数名 {指令return
}简化写法2:
函数名() {指令return
}

1.3 函数的调用

基本语法:

函数名称 参数1 参数2 …

Shell的函数参数的语法比较特殊。实际上,Shell将脚本参数和函数参数做了统一地处理。也就是说,Shell采用了相同的方法来处理脚本的参数和函数参数。

(1)调用函数:直接执行函数名即可。

函数名

(2)带参数的函数执行方法

函数名 参数

与Shell脚本一样,用户可以在Shell函数中使用位置变量来获取参数值。例如,$0 表示脚本名称,$# 来获取函数的参数个数,$1 表示第1个参数,$2 表示第2个参数等,以此类推。另外,用户还可以通过系统变量 $@ 和 $* 获取所有参数的值。

[root@openEuler ~]# cat func01.sh 
#!/bin/bashfunc() {echo "the function has $# parameters"echo "all parameters are $*"echo "all parameters are $@"echo "the script name is $0"echo "the first parameter is $1"
}func hello world[root@openEuler ~]# bash func01.sh 
the function has 2 parameters
all parameters are hello world
all parameters are hello world
the script name is func01.sh
the first parameter is hello

1.4 函数的返回值

1)在函数内用 return 退出函数并返回函数的值,在函数外用echo $?获取返回值 注意:返回值的范围只能在0~255,超过部分需除以256取余

2)在函数内用echo输出值,在函数体外可用 变量=$(函数名) 获取函数的返回值

#示例1
1.第一种方法
sum1() {sum=$[$1 + $2]echo $s
}
read -p "输入第一个数" first
read -p "输入第二个数" second
sum1 $first $second2.第二种方法
sum() {s=$[$1 + $2]    ///$1 $2 传递位置参数echo $s
}
sum $1 $2    ///$1 $2 代表执行脚本函数时命令后面跟的两个参数位置参数#示例2:获取字符串的长度[root@openEuler ~]# cat length.sh 
#!/bin/bashlength() {str=$1result=0if [ "$1" != "" ]; thenresult=${#str}fiecho "$result"
}len=$(length "abc123")echo "the string's length is $len"[root@openEuler ~]# bash length.sh 
the string's length is 6

1.5 函数的案例

1.5.1 案例1

[root@openEuler ~]# cat fun1.sh 
#!/bin/bash#定义一个将十进制转换为二进制的函数
decimal_to_bin() {NUM=$1for i in {1..8}doSUM=$[NUM % 2]$SUMlet NUM/=2doneecho $SUM
}
#定义一个分割IP的函数
split_ip() {IP=$1for i in {1..4}donum=${IP%%.*} #取十进制最左边的十进制,如192IP=${IP#*.}	#取十进制从第二个开始到最右边,如168.72.150BIN=$(decimal_to_bin num)echo -n "$BIN."done
}read -p "Please enter a valid IP address: " INIP
res=$(split_ip $INIP)
echo ${res%.*} #用于删除二进制最右边的点,%.*代表从字符串的右边开始删除,删到第一个点为止

1.5.2 案例2

写一个脚本,判定192.168.33.120-192.168.33.130之间的主机哪些在线。

要求:

1、使用函数来实现一台主机的判定过程;

 2、在主程序中来调用此函数判定指定范围内的所有主机的在线情况。

方法一:直接使用函数实现(无参数,无返回值)
[root@openEuler ~]# cat online01.sh 
#!/bin/bashonline() {for i in {120..130}; doif ping -c 1 192.168.33.$i &>/dev/nullthenecho "192.168.33.$i is up"elseecho "192.168.33.$i is unknown"fidone
}online
方法二:使用函数传参(有参数,无返回值)
[root@openEuler ~]# cat online02.sh 
#!/bin/bashonline() {if ping -c 1 $1 &>/dev/nullthenecho "$1 is up"elseecho "$1 is unknown"fi
}for i in {120..130}
doonline 192.168.33.$i
done
方法三:使用函数返回值判断(有参数,有返回值)
[root@openEuler ~]# cat online03.sh 
#!/bin/bashonline() {if ping -c 1 $1 &>/dev/nullthenreturn 0elsereturn 1fi
}
for i in {120..130}
doonline 192.168.33.$iif [ $? -eq 0 ];thenecho "192.168.33.$i is up"elseecho "192.168.33.$i is unknown"fi
done

1.5.3 案例3

写一个脚本,使用函数完成

1、函数能够接受一个参数,参数为用户名;
        判断一个用户是否存在
        如果存在,就返回此用户的shell和UID;并返回正常状态值;
        如果不存在,就说此用户不存在;并返回错误状态值;
2、在主程序中调用函数;

[root@openEuler ~]# cat userms.sh 
#!/bin/bashuser() {if id $1 &>/dev/nullthenecho "`grep ^$1 /etc/passwd | cut -d: -f3,7`"return 0elseecho "$1 does not exist"return 1fi
}read -p "please input username:" username
until [ "$username" = "quit" -o "$username" = "exit" -o "$username" = "q" ]
douser $usernameif [ $? == 0 ]; thenread -p "please input again:" usernameelseread -p "no $username, Please input again:" usernamefi
done[root@openEuler ~]# bash userms.sh 
please input username:redhat
1000:/bin/bash
please input again:root
0:/bin/bash
please input again:dakuang
dakuang does not exist
no dakuang,Please input again:hehe
hehe does not exist
no hehe,Please input again:quit

1.6 函数变量作用域

注意:默认情况下,除了与函数参数关联的特殊变量之外,其他所有的变量都有全局的有效范围。另外,在函数内部,如果没有使用local关键字进行修饰,那么函数中的变量也是全局变量。

示例1:函数的变量是全局变量[root@openEuler ~]# cat global.sh 
#!/bin/bashvar="hello world"
func() {var="orange"echo $varvar2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"[root@openEuler ~]# bash global.sh 
hello world
orange
orange
hello示例2:函数的变量使用local指定为局部变量[root@openEuler ~]# cat global02.sh 
#!/bin/bashvar="hello world"
func() {local var="orange"echo $varlocal var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"[root@openEuler ~]# bash global02.sh 
hello world
orange
hello world

1.7 递归函数

Linux的Shell也支持函数的递归调用。也就是说,函数可以直接或者间接地调用自身。在函数的递归调用中,函数既是调用者,又是被调用者。

递归函数的调用过程就是反复地调用其自身,每调用一次就进入新的一层。

示例1:根据用户输入的数值计算该数的阶乘[root@openEuler ~]# cat fact.sh 
#!/bin/bashfact() {if [$1 -eq 1]; thenresult=1elif [ $1 -gt 1]; thenlocal m=$[$1 -1]fact $mlet "result=$1 * $?"elseecho "The input value is invalid"fireturn $result# 或local n="$1"if [ "$n" -eq 0 ]; thenresult=1elselet "m=n-1"fact "$m"let "result=$n * $?"fireturn $result
}fact "$1"
echo "Factorial of $1 is $?"[root@openEuler ~]# bash fact.sh 0
Factorial of 0 is 1
[root@openEuler ~]# bash fact.sh 5
Factorial of 5 is 120示例2:使用函数递归目录/var/log,如果是文件直接输出文件名,如果是目录,则输出目录名且输出此目录下的所有目录和文件名[root@openEuler ~]# vim fact2.sh#!/bin/bashlistf () {for f in $(ls $1)doif [ -d "$1/$f" ]; thenecho "$2 directory $f"  # $2 第一次调用为一个空格,第二次调用为两个空格listf "$1/$f" "  $2"elseecho "$2 file $f"fidone
}[root@openEuler ~]# cd /var/log
[root@openEuler log]# mkdir -p aa/bb/cc
[root@openEuler log]# cd aa
[root@openEuler aa]# touch a.txt
[root@openEuler aa]# cd bb/cc
[root@openEuler cc]# touch c.txt
[root@openEuler ~]# listf  "/var/log" $()示例3:通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件[root@openEuler ~]# vim fact3.sh
#!/bin/bash#定义一个遍历PATH环境变量的函数
list_path_variable() {IFSB=$IFSIFS=$IFS':'for F in $PATHdoecho "$F"doneIFS=$IFSB
}#定义递归函数
listf() {for F in $(ls $1)doif [ -d "$1/$F" ]; thenecho "$2$F"listf "$1/$F" " $2"elseif [ ! -x "$1/$F" ]; thenecho "$2$F"fifidone
}folder=$(list_path_variable)for path in $folder
doecho $pathlistf "$path" " "
done[root@openEuler ~]# bash fact3.sh

1.8 函数库文件

为了方便地重用这些功能,可以创建一些可重用的函数。这些函数可以单独地放在函数库文件中。

函数库文件定义:

  创建一个函数库文件的过程非常类似于编写一个Shell脚本。脚本与库文件之间的唯一区别在于函数库文件通常只包括函数,而脚本中则可以既包括函数和变量的定义,又包括可执行的代码。此处所说的可执行代码,是指位于函数外部的代码,当脚本被载入后,这些代码会立即被执行,毋需另外调用。

函数库文件的调用:

  当库文件定义好之后,用户就可以在程序中载入库文件,并且调用其中的函数。在Shell中,载入库文件的命令为.,即一个圆点,其语法如下:

. ./filename 
或者
source filename

其中,参数filename表示库文件的名称,必须是一个合法的文件名。库文件可以使用相对路径,也可以使用绝对路径。另外,圆点命令和库文件名之间有一个空格。

1.创建函数库文件

[root@openEuler ~]# cat function_library.sh
#!/bin/bashaddition() {echo $[$1 + $2]
}subtraction() {echo $[$1 -$2]
}multiplication() {echo $[$1 * $2]
}division() {if [ $2 -eq 0 ]; thenecho 'Divisor cannot be 0'elseecho $[$1 / $2]fi
}factorial() {if [ $1 -eq 1 ]; thenecho 1elif [ $1 -gt 1 ]; thenlocal tmp=$[$1 -1]local res=$(factorial $tmp)echo $[$1 * res]elseecho "Please enter an integer greater than or equal to 1!"fi
}

2. 在脚本中加载函数库文件并使用

[root@openEuler ~]# cat clr_test.sh
#!/bin/bash#加载函数库文件
source /root/function_library.shv1=10
v2=5r1=$(addition $v1 $v2)
r2=$(subtraction $v1 $v2)
r3=$(multiplication $v1 $v2)
r4=$(division $v1 $v2)
r5=$(factorial $v1)
r6=$(factorial $v2)echo "$v1+$v2=$r1"
echo "$v1-$v2=$r2"
echo "$v1*$v2=$r3"
echo "$v1/$v2=$r4"
echo "$v1 factorial is $r5"
echo "$v2 factorial is $r6"

2.文本搜索工具----grep

2.1 通配符

   通配符是由shell处理的, 它只会出现在命令的“参数”里。当shell在“参数”中遇到了通配符时,shell会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换(路径扩展);否则就将该通配符作为一个普通字符传递给“命令”,然后再由命令进行处理。总之,通配符实际上就是一种shell实现的路径扩展功能。在通配符被处理后, shell会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。

通配符只是用来查找文件名和目录名

2.1.1 SHELL中的通配符

通配符说明
*匹配任意长度的任意字符,可以是0个
?匹配任意单个字符,必须是1个
[ ]匹配指定字符范围内的任意单个字符
[a-z,A-Z,0-9]匹配所有数字字母,可以不加逗号
[a-z]表示a-z,A-Y,表示a,A,b,B.....a。不包含Z
[A-Z]表示A,b,B.....z,Z。不包含a
[a-Z]表示所有大小写字母
[:upper:]所有大写字母
[:lower:]所有小写字母
[:alpha:]所有字母,大小写
[:digit:]所有数字
[:alnum:]所有数字+字母
[:blank:]水平空白字符
[:space:]水平或垂直空白字符
[:punct:]标点符号
[:print:]可打印字符
[:cntrl:]控制(非打印)字符
[:graph:]图形字符
[:xdigit:]十六进制字符
[^]匹配指定字符范围外的任意单个字符
[^0-9]相当于[^[:digit:]]
[^a-z]表示Z + 其他
[^A-Z]表示a + 其他

2.1.2 通配符实例

1、显示所有menu0开头的文件
[root@openEuler ~]# ls menu0*
menu01.sh  menu02.sh  menu03.sh  menu04.sh
2、显示所有m开头后面只有单个字符的文件
[root@openEuler ~]# ls m?
m1  m2  m3
3、显示所有m或者n开头的文件
[root@openEuler ~]# ls [mn]*
m1  m2  m3  menu01.sh  menu02.sh  menu03.sh  menu04.sh  n71  n72  n73
4、显示所有以字母开头的文件
[root@openEuler ~]# ls [a-Z]*
BC1  BC2  BC3  m1  m2  m3  menu01.sh  menu02.sh  menu03.sh  menu04.sh  n71  n72  n73
5、显示所有数字开头的文件
[root@openEuler ~]# ls [0-9]*
12a  12b  12c  12d
6、查看所有不区分大小写的字母开头的文件
[root@openEuler ~]# ls [[:alpha:]]*
BC1  BC2  BC3  m1  m2  m3  menu01.sh  menu02.sh  menu03.sh  menu04.sh  n71  n72  n73
7、查看所有以数字开头的文件
[root@openEuler ~]# ls [[:digit:]]*
12a  12b  12c  12d
8、查看所有以字母或者数字开头的文件
[root@openEuler ~]# ls [[:alnum:]]*
12a  12b  12c  12d  BC1  BC2  BC3  m1  m2  m3  menu01.sh  menu02.sh  menu03.sh  menu04.sh  n71  n72  n73

3.正则表达式

3.1 定义

   正则表达式是通过一些特殊字符的排列,用以查找、替换、删除一行或多行文字字符串,简单的说,正则表达式就是用在字符串的处理上面的一项表示式。由于正则表达式语法简练,功能强大,得到了许多程序设计语言的支持,包括Java、C++、Perl以及Shell等。

3.2 使用原因

  在进行程序设计的过程中,用户会不可避免地遇到处理某些文本的情况。有的时候,用户还需要查找符合某些比较复杂规则的字符串。对于这些情况,如果单纯依靠程序设计语言本身,则往往会使得用户通过复杂的代码来实现。但是,如果使用正则表达式,则会以非常简短的代码来完成。

3.3 使用方式

当一个正则表达式完成之后,并能够保证这个表达式一定是准确的,需要不断地测试才可以确定其正确与否。在不同的环境下,用户需要不同的工具来帮助他完成测试的过程。如果是在Shell命令行中,用户可以使用grep命令来测试。

grep家族有三大成员分别为: grep:支持使用基本正则表达式。 egrep:支持使用扩展正则表达式。 fgrep:不支持使用正则表达式,即所有的正则表达式中的元字符都将作为一般字符,仅仅拥有其字面意义,不再拥有特殊意义。

grep命令的名称来自于全局搜索正则表达式并打印文本行(Global Search Regular Expression and Print out the line)的缩写。它是一个非常古老的UNIX命令,也是一种强大的文本搜索工具。grep命令使用正则表达式来搜索文本,并且把匹配的文本行打印出来。

grep命令根据用户指定的”pattern(过滤条件)“对目标文本逐行进行匹配检查;打印出符合条件的行,即文本搜索工具。注:PATTERN即过滤条件指由文本字符及正则表达式元字符所编写的字符串。

grep命令的基本语法如下:grep [options] pattern [file…]

在上面的语法中,options表示选项,选项列表如下表。pattern表示要匹配的模式,file表示一系列的文件名。grep命令会从一个或者多个文件中搜索满足指定模式的文本行,并且打印出来。模式后面的所有的字符串参数都被看作是文件名。

-n  :显示行号
-o  :只显示匹配的内容
-q  :静默模式,没有任何输出,得用$?来判断执行成功没有,即有没有过滤到想要的内容
-l  :如果匹配成功,则只将文件名打印出来,失败则不打印,通常-rl一起用,grep -rl 'root' /etc 
-A  :如果匹配成功,则将匹配行及其后n行一起打印出来
-B  :如果匹配成功,则将匹配行及其前n行一起打印出来
-C  :如果匹配成功,则将匹配行及其前后n行一起打印出来
--color:高亮颜色显示匹配到的字符串
-c  :如果匹配成功,则将匹配到的行数打印出来
-E  :等于egrep,扩展
-i  :忽略大小写
-v  :取反,不匹配
-w:匹配单词
-r:递归搜索,不仅搜索当前目录,还要搜索其各级子目录
-s:不显示关于不存在或者无法读取文件的错误信息

在进行程序设计的过程中,用户会不可避免地遇到处理某些文本的情况。有的时候,用户还需要查找符合某些比较复杂规则的字符串。对于这些情况,如果单纯依靠程序设计语言本身,则往往会使得用户通过复杂的代码来实现。但是,如果使用正则表达式,则会以非常简短的代码来完成。

正则表达式是通过一些特殊字符的排列,用以查找、替换、删除一行或多行文字字符串,简单的说,正则表达式就是用在字符串的处理上面的一项表示式。由于正则表达式语法简练,功能强大,得到了许多程序设计语言的支持,包括Java、C++、Perl以及Shell等。

3.4 基本正则表达式

基本正则表达式(Basic Regular Expression,BRE),又称为标准正则表达式,是最早制订的正则表达式规范,仅支持最基本的元字符集。基本正则表达式是POSIX规范制订的两种正则表达式语法标准之一,另外一种语法标准称为扩展正则表达式。

元字符说明
^以某个字符开头
$以某个字符结尾
.匹配任意单字符
*对前一项进行0次或者多次重复匹配
{m,n}将前一项字符重复m-n次,{m,},{,n},{m}
[]对方括号内的单字符进行匹配
[^]不匹配方括号内的单字符
^[]匹配以某个字符开头的行
\转义字符,让一些特殊符号失效
()定义一个子表达式
词首【\<或\b】和词尾锚定【\>或者\b】其后面的任意字符必须作为单词首部出现;其前面的任意字符必须作为单词尾部出现

后项引用:后面例子中会用到。

分组:\(\)\(ab\)*后项引用\1:引用第一个左括号以及与之对应的右括号所包括的所有内容\2:\3:

正则表达式字符集

字符说明
[[:alpha:]]匹配任意一个字母,等价于 [A-Za-z]
[[:alnum:]]匹配任意一个字母或者数字,等价于 [A-Za-z0-9]
[[:digit:]]匹配任意一个数字,等价于 0-9
[[:lower:]]匹配任意一个小写字母,等价于 a-z
[[:upper:]]匹配任意一个大写字母,等价于 A-Z
[[:space:]]匹配任意一个空白符,包括空格、制表符、换行符以及分页符
[[:blank:]]匹配空格和制表符
[[:graph:]]匹配任意一个看得见的可打印字符,不包括空白字符
[[:print:]]匹配任何一个可以打印的字符,包括空白字符,但是不包括控制字符、字符串结束符‘\0’ 、 EOF 文件结束符( -1 )
[[:cntrl:]]匹配任何一个控制字符,即 ASCII 字符集中的前 32 个字符。例如换行符、制表符等
[[:punct:]]匹配任何一个标点符号,例如 “[]” 、 “ {}”或者 “,” 等
[[:xdigit:]]匹配十六进制数字,即 0-9 、 a-f 以及 A-F
[root@shell shell]# grep ^a /etc/passwd
[root@shell shell]# grep h$ /etc/passwd
[root@shell shell]# grep . /etc/passwd
[root@shell shell]# grep ro* /etc/passwd
[root@shell shell]# grep "ro\{1,2\}" /etc/passwd
[root@shell shell]# grep "ro\{1\}" /etc/passwd
[root@shell shell]# grep [a-zA-Z] /etc/passwd
[root@shell shell]# grep [a-Z] /etc/passwd
[root@shell shell]# grep [0-9] /etc/passwd
[root@shell shell]# grep [0-9a-Z] /etc/passwd  或者grep [[:alnum:]] /etc/passwd
[root@shell shell]# grep [[:space:]] /etc/passwd
[root@shell shell]# grep [^a] /etc/passwd
[root@shell shell]# grep ^[ab] /etc/passwd
[root@shell shell]# grep  "\."  file
[root@shell shell]# grep  "\(root\).*\1"  file
[root@shell shell]# grep  "ly\>"  file
[root@shell shell]# grep  "\<lo"  file
[root@shell shell]# grep "\<love\>" file
love
[root@shell shell]# grep "\blove\b" file
love

1. ^word 表示搜索以word开头的内容。

[root@openEuler ~]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@openEuler ~]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

2. word$ 表示搜索以word结尾的内容。

[root@openEuler ~]# grep bash passwd
root:x:0:0:root:/root:/bin/bash
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash
bash:x:33
[root@openEuler ~]# grep bash$ passwd
root:x:0:0:root:/root:/bin/bash
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash

3. ^$ 表示空行,不是空格。

[root@openEuler ~]# grep ^$ passwd[root@openEuler ~]# grep ^$ passwd -n
45:
49:

4. .代表且只能代表一个任意字符。

[root@openEuler ~]# grep r.t passwd
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
rot
[root@openEuler ~]# grep r..t passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
clevis:x:981:981:Clevis Decryption Framework unprivileged user:/var/cache/clevis:/sbin/nologin
root
[root@openEuler ~]# grep r...t passwd
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
unbound:x:994:988:Unbound DNS resolver:/etc/unbound:/sbin/nologin
rooot

5. * 重复0个或多个前面的字符

[root@openEuler ~]# grep r*t passwd

6. [] 匹配字符集合内任意一个字符,如[a-z]

[root@openEuler ~]# grep r[a-z]t passwd
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
rot
[root@openEuler ~]# grep r[a-z]*t passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
libstoragemgmt:x:995:989:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
setroubleshoot:x:991:984::/var/lib/setroubleshoot:/sbin/nologin
clevis:x:981:981:Clevis Decryption Framework unprivileged user:/var/cache/clevis:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash
rt
rot
root
rooot

7. [^abc]在中括号里表示非,不包含a或b或c

[root@openEuler ~]# grep r[^a-z]*t passwd
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
rt
r.t
r..t
r...t

8. {n,m} 匹配n到m次,前一个字符。

{n,} 至少N次,多了不限。 {n} n次 {,m} 至多m次,少了不限。

注意:grep要将{}转义,{},egrep不需要转义

[root@openEuler ~]# grep 'r[^a-z]\{3,\}' passwd
[root@openEuler ~]# grep -E 'r[^a-z]{3,}' passwd

通配符和正则表达式比较

(1)通配符和正则表达式看起来有点像,不能混淆。可以简单的理解为通配符只有*,?,[],{}这4种,而正则表达式复杂多了。

(2)在通配符和正则表达式中有其不一样的地方,在通配符中可以匹配任意的0个或多个字符,而在正则表达式中他是重复之前的一个或者多个字符,不能独立使用的。比如通配符可以用来匹配任意字符,而正则表达式中的""不行,他只匹配任意长度的前面的字符(如果想匹配任意字符,那么就需要用.符号,通配符中的 *= 正则表达式中的.*

(3)使用场景:通配符 是文件名。正则表达式 文本内容

(4) 使用命令 通配符 find rm ls cp 由shell解析; 正则表达式 vi grep sed awk

3.5 扩展正则表达式

扩展正则表达式(Extended Regular Expression,ERE)支持比基本正则表达式更多的元字符,但是扩展正则表达式对有些基本正则表达式所支持的元字符并不支持。前面介绍的元字符“^”、“$”、“.”、“*”、“[]”以及“[^]”这6个元字符在扩展正则表达式都得到了支持,并且其意义和用法都完全相同,不再重复介绍。接下来重点介绍一下在扩展正则表达式中新增加的一些元字符。

元字符说明
?将前一项字符进行0次或者1次的重复匹配
+将前一项进行1次或者多次的重复匹配
(|)匹配|符号左边或者右边的字符
[root@shell shell]# grep  -E ro? /etc/passwd
[root@shell shell]# grep  -E ro+ /etc/passwd
[root@shell shell]# grep  -E "(root|adm|ssh)" /etc/passwd

 案例

1、显示/etc/passwd文件中以bash结尾的行;[root@openEuler ~]# grep bash$ /etc/passwd
root:x:0:0:root:/root:/bin/bash
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash2、找出/etc/passwd文件中的三位或四位数;[root@openEuler ~]# grep '[[:digit:]]\{3,4\}' /etc/passwd
[root@openEuler ~]# grep -E '[[:digit:]]{3,4}' /etc/passwd3、找出/etc/grub2.cfg文件中,以至少一个空白字符开头,后面又跟了非空白字符的行;[root@openEuler ~]# grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg4、找出"netstat  -tan”命令的结果中,以‘LISTEN’后跟0个或多个空白字符结尾的行;[root@openEuler ~]# netstat -tan | grep "LISTEN[[:space:]]*$"5、找出"fdisk  -l“命令的结果中,取出硬盘路径;
[root@openEuler ~]# fdisk -l | grep Disk | grep /dev/nv | cut -d: -f 1 | cut -d " " -f26、找出”ldd  /usr/bin/cat“命令的结果中文件路径;[root@openEuler ~]# ldd /usr/bin/cat | egrep [[:blank:]]\+/[[:graph:]]*7、找出/proc/meminfo文件中,所有以大写或小写s开头的行
[root@openEuler ~]# grep -i ^S /proc/meminfo8、显示当前系统上root、centos或spark用户的相关信息;[root@openEuler ~]# grep -E ^"(root|centos|spark)" /etc/passwd
[root@openEuler ~]# egrep ^"(root|centos|spark)" /etc/passwd9、echo输出一个绝对路径,使用egrep取出其基名;[root@openEuler ~]# echo /mnt/sdc/ | grep -E -o "[^/]+/?$" | cut -d "/" -f 110、找出ifconfig命令结果中的1-255之间的整数;[root@openEuler ~]# ifconfig | egrep -w "[1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]"11. 找出ifconfig命令输出中的所有IP地址
[root@openEuler ~]# ifconfig | egrep -o "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

4.shell编程之sed

4.1 sed工作原理

  sed是一种流编辑器,它是文本处理中非常有用的工具,能够完美的配合正则表达式使用,处理时,把当前处理的行存储在临时缓冲区中,称为模式空间,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。

4.2 sed基本语法

sed OPTIONS… [SCRIPT] [INPUTFILE…]

常用的选项:

-n--quiet--silent:不输出模式空间中的内容,使用安静模式,在一般sed的用法中,所有来自STDIN的数据一般都会被列出到屏幕上,但如果加上-n参数后,则只有经过sed特殊处理的那一行才会被列出来;

-i:直接编辑原文件,而不是由屏幕输出,默认不对原文件进行操作;

-e:直接在命令行模式上进行sed的动作编辑,多个子命令之间也可以用分号隔开;sed -e 'command1;command2... filename或者sed -e 'command1' -e 'command2' ……filename

-r:使用扩展正则表达式;

-f:直接将sed的动作写在一个文件内,-f filename则可以执行filename内的sed动作。

4.3 模式空间中的编辑操作

4.3.1 地址定界

地址定界示例说明
不写地址定界表示对文件所有行进行处理
num1,num21,3或者1,$对文件的1-3行内容进行处理;如果是$表示文件的最后一行
num1,+N1,+3对文件的num1行以及以后的N行内容进行处理
first~step1~2对文件的1,3,5,7,……的行内容进行处理
/pattern//^root/,/r/I对任何能够被正则表达式匹配到的行进行处理
\%pattern%\%/r%可以使用其他的边界符号(例如#),对任何能够被正则表达式匹配到的行进行处理
/pattern1/,/pattern2//^root/,/^adm/表示正则表达式1和正则表达式2匹配到的行和两个正则表达式之间的所有行
0,/pattern1/或者1,/pattern1/0,/^adm/从第一行开始到能够被正则表达式匹配到的行之间的所有内容

4.3.2 常用编辑命令

对文件行内容的编辑命令说明示例
d删除匹配到的行[root@node13 ~]#sed '1 d' file [root@node13 ~]#sed '/^$/d' /etc/hosts
p打印匹配到的行[root@node13 ~]#sed '1p' file
a 文本内容将文本内容添加到匹配到的行的下一行[root@node13 ~]#sed '1 a hello' file
i 文本内容将文本内容添加到匹配到的行上一行[root@node13 ~]#sed '1 i hello' file
c 文本内容用文本内容替换匹配到的所有行[root@node13 ~]#sed '1,3 i hello' file
s/pattern/replacement/flag根据正则表达式进行匹配,将匹配到的内容替换为replacement,flag可以指定g(表示全局替换,默认只替换每行第一个)num1(表示对匹配到的第几个内容进行替换),i(不区分大小写),p(如果成功替换则打印)[root@node13 ~]#sed '1 s#\<print\>#echo#g' file [root@node13 ~]# sed '1 s/\bprint\b/echo/2' file
r读入文件内容追加到匹配行后面[root@node13 ~]#sed '2 r /root/ceshi.sh' file
R读入文件一行内容追加到匹配行后面[root@node13 ~]#sed '2 R /root/ceshi.sh' file
w /dir/filename将匹配到的内容另存到/dir/filename中[root@node13 ~]# sed '1 w /dir1/file1' file
sed 's/north/hello/' datafile --替换每行第一个north
sed 's/north/hello/g' datafile --全部替换
sed '1 s/north/hello/g' datafile --替换第一行所有的north
sed '1 s/north/hello/' datafile --替换第一行第一个north
sed '1 s/north/hello/2' datafile --只替换第一行第二个north

巧用替换删除内容(不是删除行)

sed 's/north//' datafile --删除所有行的第一个north
sed 's/north//g' datafile --删除全部的north
sed '1 s/north//2' datafile --删除第一行第二个
sed 's/^.//' datafile --删除每行第一个字符
sed 's/^\(..\)./\1/' datafile --删除第3个字符
sed 's/^\<[a-Z]*[a-Z]\>//' datafile --删除每行第一个单词

特殊符号说明
对指定行以外的所有行应用命令
=打印当前行行号
~“first~step”表示从first行开始,以步长step递增
&代表匹配到的内容
;实现一行命令语句可以执行多条sed命令
{}对单个地址或地址范围执行批量操作
+地址范围中用到的符号,做加法运算
[root@node13 ~]# sed '1 ! p' file      #打印除了第一行以外的行内容
[root@node13 ~]# sed '/echo/ = ' file
[root@node13 ~]# sed '1 s/echo/:&:/' file
[root@node13 ~]# sed '1 s/echo/:&:/; 3 s/bea/aaa/' file
[root@node13 ~]# sed '1,3 {p;=}' file  等同于[root@node13 ~]# sed '1p;2p;3p;1 =;2=;3 =' file

案例

准备数据
cat -n openlab.txt
My name is jock.
I teach linux.
I like play computer game.
My qq is 24523452
My website is http://www.xianoupeng.com
My website is http://www.xianoupeng.com
My website is http://www.xianoupeng.com
My website is http://www.xianoupeng.com
My website is http://www.xianoupeng.com
My website is http://www.xianoupeng.com
1.输出文件第2,3行的内容
sed -n '2,3p' openlab.txt
I teach linux.
I like play computer game.
2. 过滤出含有linux的字符行串
sed -n '/linux/p' openlab.txt
I teach linux.
3.删除含有game的行
sed '/game/p' openlab.txt -n
I like play computer game.sed '/game/d' openlab.txtcat -n openlab.txt
My name is jock.
I teach linux.
I like play computer game.
My qq is 24523452
My website is http://www.xianoupeng.comsed '/game/d' openlab.txt -icat -n openlab.txt
My name is jock.
I teach linux.
My qq is 24523452
My website is http://www.xianoupeng.com
4.将文件中的My全部替换为His

(s内置符配合g,代表全局替换,中间的"/"可以替换为"#@/"等)

sed '/s/My/His/g' openlab.txt
5.替换所有My为His,同时QQ号为88888888
sed -e 's/My/His/g' -e 's/24523452/88888888/g' openlab.txt
6.在文件第二行追加内容 a 字符功能,写入到文件,还要添加-i
# 在第二行下插入
sed -i '2a I am useing sed command' openlab.txt
添加多行信息,用换行符“\n”
sed -i "3a i like linux very much.\nand you?" openlab.txt

在每一行下面插入新内容

sed "a --------" openlab.txt
7、在第二行上面插入内容
# 在第二行上插入
sed -i '2i I am boy.' openlab.txt

面试题解析

文件内容如下:123abc456456def123567abc789789def567要求输出:456ABC123123DEF456789ABC567567DEF789# sed -r 's/([0-9]{3})(.*)([0-9]{3})/\3\2\1/' b.txt | tr -s '[a-z]' '[A-Z]'456ABC123123DEF456789ABC567567DEF789

5.shell编程之awk

5.1 awk定义

  awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具。简单地讲,awk是一种处理文本数据的编程语言。awk的设计使得它非常适合于处理由行和列组成的文本数据。而在Linux或者UNIX环境中,这种类型的数据是非常普遍的。

  除此之外,awk 还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达式,变量以及函数等一系列的程序设计语言所具备的特性。它从C语言中获取了一些优秀的思想。awk程序可以读取文本文件,对数据进行排序,对其中的数值执行计算以及生成报表等。

5.2 工作流程

awk命令的基本语法如下:

awk 'pattern { actions }'

在上面的语法中,pattern表示匹配模式actions表示要执行的操作。以上语法表示,当某个文本行符合pattern指定的匹配规则时,执行actions所执行的操作。在上面的语法中,pattern和actions都是可选的,但是两者必须保证至少有一个。如果省略匹配模式pattern,则表示对所有的文本行执行actions所表示的操作;如果省略actions,则表示将匹配成功的行输出到屏幕。

对于初学者来说,搞清楚awk的工作流程非常重要。只有在掌握了awk的工作流程之后,才有可能用好awk来处理数据。在awk处理数据时,它会反复执行以下4个步骤:

(1)自动从指定的数据文件中读取行文本。

(2)自动更新awk的内置系统变量的值,例如列数变量NF、行数变量NR、行变量$0以及各个列变量$1、$2等等。

(3)依次执行程序中所有的匹配模式及其操作。

(4)当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有未读取的数据行,则返回到第(1)步,重复执行(1)~(4)的操作。

5.3 基本语法

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'  [INPUTFILE…]

5.3.1 awk的输出

(1)print item1,item2,……

  • 各项目之间使用逗号隔开,而输出时则以空白字符分隔
  • 输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,然后再输出;
  • print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print “ ”;
[root@localhost ~]# awk 'BEGIN { print "line one\nline two\nline three"}'
line one
line two
line three
[root@localhost ~]# awk 'BEGIN{print "This","is","test"}'
This is test
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd | head -n 3
root 0
bin 1
daemon 2

(2)printf("format\n", [arguments])

format是一个用来描述输出格式的字符串,format格式的指示符都以%开头,后跟一个字符,如下:

%c: 显示字符的ASCII码;

%d, %i:十进制整数;

%e, %E:科学计数法显示数值;

%f: 显示浮点数;

%g, %G: 以科学计数法的格式或浮点数的格式显示数值;

%s: 显示字符串;

%u: 无符号整数;

%%: 显示%自身;

  • 修饰符

N:  显示宽度;

-:  左对齐;

+:显示数值符号

  • printf语句不会自动打印换行符;\n
  • 通常将字符串常量用双引号引起来
  • argument为一个参数列表,表示用来显示的数据,可以是变量名等,多个参数之间用逗号隔开。

(3)输出重定向

print items > output-file

print items >> output-file

print items | command

root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3 > "test1" }' /etc/passwd

5.3.3 awk的变量

    与其他的程序设计语言一样,awk本身支持变量的相关操作,包括变量的定义和引用,以及参与相关的运算等。此外,还包含了许多内置的系统变量。 变量的作用是用来存储数据。变量由变量名和值两部分组成,其中变量名是用来实现变量值的引用的途径,而变量值则是内存空间中存储的用户数据。 awk的变量名只能包括字母、数字和下划线,并且不能以数字开头。例如abc、az以及a123都是合法的变量名,而123abc则是非法的变量名。另外,awk的变量名是区分大小写的,因此,X和x分别表示不同的变量。 在awk中定义变量的方法非常简单,只要给出一个变量名并且赋予适当的值即可。awk中的变量类型分为两种,分别为字符串和数值。但是在定义awk变量时,毋需指定变量类型,awk会根据变量所处的环境自动判断。如果没有指定值,数值类型的变量的缺省值为0,字符串类型的变量的缺省值为空串。 awk提供了许多非常实用的系统变量,例如字段变量、字段数变量以及记录数变量等。

(1)awk内置变量

变量说明
$0记录变量,表示当前正在处理的记录
$n字段变量,其中n为整数,且n大于1。表示第n个字段的值
NF整数值,表示当前记录(变量$0所代表的记录)的字段数
NR整数值,表示awk已经读入的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数。(显示的是文件的每一行的行号)
FNR与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
FILENAME表示正在处理的数据文件的名称
FS输入字段分隔符,默认值是空格或者制表符,可使用-F指定分隔符
OFS输出字段分隔符 ,OFS=”#”指定输出分割符为#。
RS记录分隔符,默认值是换行符 \n
ENVIRON当前shell环境变量及其值的关联数组;

示例:

[root@localhost ~]# echo "this is" > test.txt
[root@localhost ~]# awk 'BEGIN {OFS="#"} {print $1,$2,"a","test"}' test.txtthis#is#a#test
[root@localhost ~]# awk 'BEGIN{print 		ENVIRON["PATH"]}'	/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

(2)用户自定义变量

   awk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。awk变量名称区分字符大小写。

使用赋值语句进行赋值:
[root@localhost ~]# awk 'BEGIN{test="hello";print test}'
hello
在命令行中使用-v选项赋值:
[root@localhost ~]# awk -v test="hello" 'BEGIN {print test}'
hello

5.3.4 awk的操作符

  awk是一种编程语言环境,因此,它也支持常用的运算符以及表达式,例如算术运算、逻辑运算以及关系运算等。

(1)awk支持常用的算术运算,这一点与其他的程序设计语言基本相同。

运算符说明举例
+加法运算1+2表示计算1和2的和
-减法运算82-2表示计算82和2的差
*乘法运算2*5表示计算2和5的积
/除法运算6/3表示计算6和2的商
%求模运算5/2表示计算5除以2的余数
^指数运算2^3表示计算2的3次方

示例:

[root@localhost ~]# awk 'BEGIN{x=2;y=3;print x**y,x^y,x*y,x/y,x+y,x-y,x%y}'
8 8 6 0.666667 5 -1 2

(2)赋值运算符

运算符说明举例
=赋值运算x=5表示将数值5赋给变量x
+=复合赋值运算,表示将前后两个数值相加后的和赋给前面的变量x+=5表示先将x的值与5相加,然后再将和赋给变量x,等价于x=x+5
-=复合赋值运算,表示将前后两个数值相减后的值赋给前面的变量x-=5表示先将x的值减去5,然后再将得到的差赋给变量x,等价于x=x-5
*=复合赋值运算,表示前后两个数的乘积赋给前面的变量表示先将x的值乘以5,然后再将得到的乘积赋给变量x
/=复合赋值运算,表示前后两个数值的商赋给前面的变量表示先将变量x除以5,再将商赋给变量x
%=复合赋值运算,表示将前面的数值除以后面的数值所得的余数赋给前面的变量将变量x与5相除后的余数赋给变量x
^=复合运算符,表示将前面的数值的后面数值次方赋给前面的变量x^=3表示将变量x的3次方赋给变量x

(3)条件运算符

   awk中的条件运算符只有一个,其语法如下:`expression?value1:value2`

这是一个三目运算符,当表达式expression的值为真时,返回值为value1;否则,返回值为value2。

示例:

[root@localhost ~]# cat file 
3 6
10 9
3 3
[root@localhost ~]# awk '{max=$1>$2?$1:$2;print NR,"max=",max}' file
1 max= 6
2 max= 10
3 max= 3

(4)逻辑运算符

awk支持3种逻辑运算,分别为逻辑与、逻辑或和逻辑非

运算符说明举例
&&逻辑与,当前后两个表达式的值全部为真时,其运算结果才为真1>2&&3>2的值为假
||逻辑或,前后两个表达式只要有一个为真,则其运算结果为真。当两个表达式的值都为假时,其运算结果才为假1>2&&3>2的值为真
逻辑非,当表达式的值为真时,其运算结果为假;当表达式的值为假时,其运算结果为真!(1>2)的值为真

(5)关系运算符

运算符说明举例
>大于5>2的值为真
>=大于或者等于8>=8的值为真
<小于8<12的值为真
<=小于或者等于4<=7的值为真
==等于9==9的值为真
!=不等于1!=3的值为真
~匹配运算符$1 ~ /^T/表示匹配第一个字段以字符T开头的记录
!~不匹配运算符$1 !~ /a/表示匹配第一个字段不含有字符a的记录
[root@localhost test11]# awk '$1~/^w/ {print}' file
wangmei 70
[root@localhost ~]# awk -F: 'BEGIN {printf "%-10s %-5s %-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-10s %-5s %-15s\n",$1,$3,$7}' /etc/passwd
user       uid   shell
root       0     /bin/bash
bin        1     /sbin/nologin
[root@localhost ~]# awk -F: 'BEGIN {printf "%-10s %-5s %-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-10s %-5s %-15s\n",$1,$3,$7} END{print "-------end---------"}' /etc/passwd
user       uid   shell
root       0     /bin/bash
bin        1     /sbin/nologin
-------end---------
说明:$3==0,$7~"nologin"表示匹配符合条件1到条件2之间的所有行(成对多次匹配),如果条件2不成立,则一直匹配到文件尾部
[root@localhost ~]# cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}'  查阅/etc/passwd文件第三列小于10以下的数据,并且仅列出账号与第三列。但是这样的写法会导致第一行无法正确显示出来,由于读入第一行的时候,变量$1,$2……默认还是以空格符为分隔的,定义的FS=“:”仅能在第二行后才开始生效。可以使用BEGIN这个关键字来达到从第一行读入。
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
[root@localhost ~]# cat /etc/passwd | awk -F : '$3 < 10 {print $1 "\t" $3}'
说明:$3变量是空值,但是后面与之作比较的是整数,所以$3的值是0,满足条件,所以打印$1的结果,在此打印$3的结果时$3是空串。

(6)其他运算符

  awk还支持其他的一些运算符,例如正号+、负号-、自增++以及自减--等,这些运算符的使用方法与其他的语言的使用方法完全相同。

5.3.5 awk的模式

  在awk中,匹配模式处于非常重要的地位,它决定着匹配模式后面的操作会影响到哪些文本行。awk中的匹配模式主要包括关系表达式、正则表达式、混合模式,BEGIN模式以及END模式等。

(1)关系表达式

  awk提供了许多关系运算符,例如大于>、小于<或者等于==等。awk允许用户使用关系表达式作为匹配模式,当某个文本行满足关系表达式时,将会执行相应的操作。

[root@localhost test11]# cat file 
liming 80
wangmei 70
zhangsan 90
lisi 81
[root@localhost test11]# awk '$2 > 80 {print}' file
zhangsan 90
lisi 81

(2)正则表达式

  awk支持以正则表达式作为匹配模式,与sed一样,用户需要将正则表达式放在两条斜线之间,其基本语法如下:/regular_expression/

[root@localhost test11]# awk '/^l/{print}' file
liming  80
lisi	81
[root@localhost test11]# awk '/^l|z/{print}' file
liming  80
zhangsan  90
lisi	81

(3)混合模式

  awk不仅支持单个的关系表达式或者正则表达式作为模式,还支持使用逻辑运算符&&、||或者!将多个表达式组合起来作为一个模式。其中,&&表示逻辑与,||表示逻辑或,!表示逻辑非。

[root@localhost test11]# awk '/^l/ && $2>80 {print}' file
lisi	81

(4)区间模式

  awk还支持一种区间模式,也就是说通过模式可以匹配一段连续的文本行。区间模式的语法如下:

pattern1, pattern2

其中,pattern1和pattern2都是前面所讲的匹配模式,可以是关系表达式,也可以是正则表达式等。当然,也可以是这些模式的混合形式。

[root@localhost test11]# awk '/^l/ && $2>80 {print}' file
lisi	81

(5)BEGIN模式

  BEGIN模式是一种特殊的内置模式,其成立的时机为awk程序刚开始执行,但是又尚未读取任何数据之前。因此,该模式所对应的操作仅仅被执行一次,当awk读取数据之后,BEGIN模式便不再成立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1次的代码放在BEGIN模式对应的操作中。

[root@localhost test11]# cat 1.sh 
#!/bin/awk -f
BEGIN {print "hello,world"}
[root@localhost test11]# ./1.sh 
hello,world
[root@localhost ~]# awk -F: 'BEGIN {printf "%-15s %-3s %-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-15s %-3s %-15s\n",$1,$3,$7}' /etc/passwd

(6)END模式

  END模式是awk的另外一种特殊模式,该模式成立的时机与BEGIN模式恰好相反,它是在awk命令处理完所有的数据,即将退出程序时成立,在此之前,END模式并不成立。无论数据文件中包含多少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1次。因此,一般情况下,用户可以将许多善后工作放在END模式对应的操作中。

[root@localhost test11]# cat 2.sh 
#! /bin/awk -f
BEGIN {print "scores report"print "================================="
}
{ print }
END {print "================================"print "printing is over"
}
[root@localhost test11]# ./2.sh file 
scores report
=================================
liming  80
wangmei  70
zhangsan  90
lisi	81
================================
printing is over
[root@localhost ~]# awk -F: 'BEGIN {printf "%-15s %-3s %-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-15s %-3s %-15s\n",$1,$3,$7} END {print "-----End file-----"}' /etc/passwd

5.3.6 awk控制语句

  作为一种程序设计语言,awk支持程序的流程控制,例如条件判断、循环以及其他的一些流程控制语句,例如continue、break以及exit等。掌握这些基本的流程控制语句,对于编写出结构良好的程序非常重要。

(1)if语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:

if (expression) 
{statement1statement2
}
else
{statement3statement4
}[root@localhost test11]# cat 3.sh 
#! /bin/awk -f
{if ($2 >= 90) {print $1,"A"}else {if($2 >= 80 && $2 < 90){print $1,"B"}else{print $1,"C"}}
}
[root@localhost test11]# cat file 
liming  80
wangmei  70
zhangsan  90
lisi	81
[root@localhost test11]# ./3.sh  file 
liming B
wangmei C
zhangsan A
lisi B
[root@localhost ~]# awk -F: '{if ($1=="root") printf "%-10s %-15s\n", $1, "Admin"; else printf "%-10s %-15s\n",$1, "Common User"}' /etc/passwd | head -n 3
[root@localhost ~]# awk '{if ($1>$2) print NR,"max =",$1;else print NR,"max =",$2}' file

(2)while语句是另外一种常用的循环结构,其语法如下:

写法1:
while (expression)
{
statement1
statement2
……
}
写法2:
do {
statement1
statement2
...
}while (expression)

当表达式expression的值为真时,执行循环体中的statement1以及statement2等语句。如果循环体中只包含一条语句,则可以省略大括号。

[root@localhost ~]# awk 'BEGIN{while(i<=100) {sum+=i;i++}print "sum=",sum}'
sum= 5050
[root@localhost test11]# cat 4.sh 
#! /bin/awk -f
BEGIN {i=0while (++i <= 9){print i^2}
}
[root@localhost test11]# ./4.sh 
1
4
9
16
25
36
49
64
81

(3)for语句

for(expression1; expression2; expression3)
{statement1statement2...
}

for循环语句通常用在循环次数已知的场合中,其语法如下:

  在上面的语法中,表达式expression1通常用来初始化循环变量,表达式expression2通常用来指定循环执行的条件,表达式expression3通常用来改变循环变量的值。当表达式expression2的值为真时,执行循环体中的语句。

[root@localhost ~]# awk 'BEGIN {for(i=1;i<=100;i++){sum+=i;}print "sum=",sum}'
sum= 5050
[root@localhost test11]# cat 6.sh 
#! /bin/awk -f
BEGIN {for(i=1;i<=9;i++){for(j=1;j<=i;j++){if(i*j<10){row=row"   "i*j}else{row=row"  "i*j}}print rowrow=""}
}
[root@localhost test11]# ./6.sh 12   43   6   94   8  12  165  10  15  20  256  12  18  24  30  367  14  21  28  35  42  498  16  24  32  40  48  56  649  18  27  36  45  54  63  72  81for循环还可以用来遍历数组元素:	语法: for(变量 in 数组){语句}
#统计用户的shell
[root@localhost ~]# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd

(4)break语句

  用户可以通过使用break语句在适当的时机退出for以及while等循环结构,而不必等到循环结构自己退出。

(5)continue语句

  continue语句的主要功能是跳过循环结构中该语句后面的尚未执行的语句。break语句与continue语句的功能有着明显的区别,前者是直接退出循环结构,而后者是跳过循环体中尚未执行的语句,重新执行下一次循环。

(6)next语句

  next语句的功能与continue语句非常相似,但是next语句并不是用在循环结构中,而是用在整个awk程序中。当awk执行程序时,如果遇到next语句,则提前结束对本行文本的处理,awk会继续读取下一行数据,并且从第一个模式及其操作开始执行。

例如,下面的命令将显示其ID号为奇数的用户:[root@localhost ~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd  |head -n 3bin 1adm 3sync 5

(7)exit语句

exit语句的功能是终止awk程序的执行

5.3.7 awk使用数组

(1)定义数组

array[index]:数组array的索引可以是任意字符串,如果数组某元素事先不存在,那么awk会自动创建此元素并初始化为空串。

(2)使用for循环可以遍历数组元素:for(var in 数组) {语句}

  • var用于引用数组下标

#统计用户的shell
[root@localhost ~]# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
[root@localhost ~]# netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print
a, S[a]}'
ESTABLISHED 1
LISTEN 10

(3)删除数组变量

delete array[index]  

面试题解析

文件内容如下1.1.1.1      111.1.1.1      221.1.1.1      331.1.1.1      442.2.2.2      112.2.2.2      222.2.2.2      332.2.2.2      44要求使用sed及awk分别将文件输出:1.1.1.1       11  22  33  442.2.2.2       11  22  33  44# awk '{s[$1]=s[$1]" "$2} END {for (k in s) {print k,s[k]}}' c.txt1.1.1.1  11 22 33 442.2.2.2  11 22 33 44# sed   -r   'N;N;N;s/\n/ /g;s/(.*)(11 )(.*)(22 )(.*)(33 )(.*)(44)/\1\2\4\6\8/' c.txt 1.1.1.1      11 22 33 442.2.2.2      11 22 33 44

相关文章:

Shell脚本编程3(函数+正则表达式)

1.函数 1.1 定义 简单来讲&#xff0c;所谓函数就是把完成特定功能&#xff0c;并且多次使用的一组命令或者语句封装在一个固定的结构中&#xff0c;这个结构我们就叫做函数。从本质上讲&#xff0c;函数是将一个函数名与某个代码块进行映射。也就是说&#xff0c;用户在定义了…...

【C++】语言深处的“精灵”:探索内存的奥妙

这里我们要知道&#xff0c;我们编写一个程序&#xff0c;这个程序中的变量是存储在哪个区域的 栈一般是用于静态的分配内存的&#xff0c;但也可以动态的分配内存&#xff0c; 堆是用于动态的分配内存的&#xff0c;不能静态的分配内存 栈&#xff1a; 通常是向低地址方向…...

c语言第一个小游戏:贪吃蛇小游戏03

我们为贪吃蛇的节点设置为一个结构体&#xff0c;构成贪吃蛇的身子的话我们使用链表&#xff0c;链表的每一个节点是一个结构体 显示贪吃蛇身子的一个节点 我们这边node就表示一个蛇的身体 就是一小节 输出结果如下 显示贪吃蛇完整身子 效果如下 代码实现 这个hasSnakeNode(…...

51 单片机头文件 reg51.h 和 reg52.h 详解

51 单片机头文件详解 51 单片机的头文件reg51.h和reg52.h是开发中非常重要的文件,它们定义了单片机的特殊功能寄存器 (SFR) 和位地址。以下是对这两个头文件的详细解析: 1. 头文件概述 reg51.h:针对标准 8051 单片机(4KB ROM, 128B RAM) reg52.h:针对增强型 8052 单片…...

让 - 艾里克・德布尔与斯普林格出版公司:科技变革下的出版业探索

在数字化浪潮席卷全球的当下&#xff0c;传统出版行业面临着前所未有的挑战与机遇。《对话 CTO&#xff0c;驾驭高科技浪潮》的第 10 章聚焦于让 - 艾里克・德布尔&#xff08;Jean - Eric Debeure&#xff09;及其所在的斯普林格出版公司&#xff08;Springer Publishing Comp…...

[python] 面向对象的三大特性-封装及新式类

一 继承 继承是指一个类&#xff08;子类&#xff09;可以继承另一个类&#xff08;父类&#xff09;的属性和方法&#xff0c;并可以在其基础上进行扩展或修改。 子类可以继承父类的属性和方法,包括私有属性和隐藏属性 &#x1f4a1; 核心思想&#xff1a; 避免重复代码&…...

winreg查询Windows注册表的一些基本用法

注册表是Windows操作系统中用于存储配置信息的数据库。它包含了关于系统硬件、已安装的应用程序、用户账户设置以及系统设置的信息。 特别地&#xff0c;当我们需要某些软件的配置配息时&#xff0c;主要在HKEY_CURRENT_USER和HKEY_LOCAL_MACHINE下的SoftWare内进行查询操作。 …...

DHCP自动分配IP

DHCP自动分配IP 练习1 路由器 Router>en Router#conf t Router(config)#ip dhcp pool ip10 //创建DHCP地址池 Router(dhcp-config)#network 192.168.20.0 255.255.255.0 // 配置网络地址和子网掩码 Router(dhcp-config)#default-router 192.168.20.254 //配置默认网关 Rou…...

互联网大厂Java求职面试实战:Spring Boot与微服务场景深度解析

&#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通 &#x1f601; 2. 毕业设计专栏&#xff0c;毕业季咱们不慌忙&#xff0c;几百款毕业设计等你选。 ❤️ 3. Python爬虫专栏…...

TDengine 在金融领域的应用

简介 金融行业正处于数据处理能力革新的关键时期。随着市场数据量的爆炸式增长和复杂性的日益加深&#xff0c;金融机构面临着寻找能够高效处理大规模、高频次以及多样化时序数据的大数据处理系统的迫切需求。这一选择将成为金融机构提高数据处理效率、优化交易响应时间、提高…...

十三、动态对象创建(Dynamic Object Creation)

十三、动态对象创建&#xff08;Dynamic Object Creation&#xff09; 目录 13.1 对象创建&#xff08;Object creation&#xff09;13.2 new / delete 操作符13.3 数组的 new 与 delete13.4 总结 背景说明 有时候我们需要知道程序中对象的数量、类型和声明周期&#xff0c;…...

cursor Too many报错 显示锁机器码怎么办?也就是Cursor的

22. Too many报错 显示锁机器码怎么办&#xff1f;也就是Cursor的 文档出自&#xff1a;https://www.kdocs.cn/l/cp5GpLHAWc0p...

window 显示驱动开发-将虚拟地址映射到内存段(二)

在将虚拟地址映射到段的一部分之前&#xff0c;视频内存管理器调用显示微型端口驱动程序的 DxgkDdiAcquireSwizzlingRange 函数&#xff0c;以便驱动程序可以设置用于访问可能重排的分配位的光圈。 驱动程序既不能将偏移量更改为访问分配的 PCI 光圈&#xff0c;也不能更改分配…...

Linux 软硬连接详解

目录 一、软链接&#xff08;Symbolic Link&#xff09; ‌定义与特性 ‌实现方法‌使用 ln -s 命令&#xff1a; 二、硬链接&#xff08;Hard Link&#xff09; 1、是什么 2、工作机制 3、实现方式 一、软链接&#xff08;Symbolic Link&#xff09; ‌定义与特性 定义…...

虚拟主机与独立服务器:哪个更好?

在选择网站主机提供商时&#xff0c;你可以选择独立服务器或者与其他用户共同使用的虚拟主机。这个决定不仅仅是基于价格&#xff0c;还有很多其他因素需要考虑。接下来&#xff0c;我们就来详细了解一下虚拟主机和独立服务器的区别。 虚拟主机和独立服务器的区别 独立服务器是…...

MiMo-7B-RL调研

结论 MiMo 在数学推理和代码竞赛的评测中表现出色&#xff0c;但是相较于 OpenAI 的 o1-mini 和阿里的 QwQ-32B-Preview 等更大规模的模型&#xff0c;推理耗时更长&#xff08;4 到 10 倍&#xff09;&#xff0c;花费 Token 更多。 链接 开源地址: https://huggingface.co/…...

vue-i18n 优化

语言包管理优化&#xff1a; 当前语言包文件&#xff08;en.json 和 zh.json&#xff09;过大&#xff0c;建议按模块拆分建议的目录结构&#xff1a; src/assets/i18n/ ├── modules/ │ ├── common/ │ ├── dashboard/ │ ├── report/ │ └── system/ …...

全栈工程师实战手册:LuatOS日志系统开发指南!

本文聚焦LuatOS-log库的实战应用场景&#xff0c;通过完整案例演示日志模块集成、格式定制及远程同步方案&#xff0c;帮助全栈开发者构建灵活可靠的日志管理框架。下面&#xff0c;我们一起来认识LuatOS的log库&#xff01; 一、 log.info() log info()主要打印一些正常的…...

Java知识库网站整理

本文主要推荐一些高质量的Java知识库和学习网站&#xff0c;涵盖了从基础到高级的Java技术&#xff0c;包括JVM底层原理、框架源码分析、面试题集、全栈知识体系等。如果你有其他优秀的Java学习网站推荐&#xff0c;欢迎在评论区分享&#xff01; 如遇到以下网站不能打开请检查…...

详解 IRC协议 及客户端工具 WeeChat 的使用

本文将详细介绍 Internet Relay Chat&#xff08;IRC&#xff09;协议及其历史、基本概念、核心功能&#xff0c;以及流行的 IRC 客户端 WeeChat 的安装、配置和使用方法。内容力求准确、详尽&#xff0c;涵盖 IRC 的技术背景、使用场景&#xff0c;以及 WeeChat 的高级功能和实…...

数据出境的安全合规思考

数据已成为新型国家战略性资产&#xff0c;其经济和战略价值在全球数字经济发展中愈加凸显。跨境数据流动既是重要的经济纽带&#xff0c;又是新兴的经济秩序博弈焦点&#xff0c;对于推动经济全球化发展意义重大。然而&#xff0c;跨境数据流动也面临诸多问题与挑战&#xff0…...

【技巧】使用frpc点对点安全地内网穿透访问ollama服务

回到目录 【技巧】使用frpc点对点安全地内网穿透访问ollama服务 0. 为什么需要部署内网穿透点对点服务 在家里想访问单位强劲机器&#xff0c;但是单位机器只能单向访问互联网&#xff0c;互联网无法直接访问到这台机器。通过在云服务器、单位内网服务器、源端访问机器上&am…...

Go语言即时通讯系统 开发日志day1

Go语言即时通讯系统开发日志day1&#xff0c;主要模拟实现的一个简单的发送消息和接受消息的小demo&#xff0c;因为也才刚学习go语言的语法&#xff0c;对go的json、net/http库了解不多&#xff0c;所以了解了一下go语言的encoding/json库和net/http库&#xff0c;以及websock…...

多线程访问Servlet如何谨慎处理共享资源

1. 避免共享状态&#xff08;最佳实践&#xff09; 核心思想&#xff1a;Servlet 本身应设计为无状态&#xff08;Stateless&#xff09;&#xff0c;不依赖实例变量存储请求相关数据。 实现方式&#xff1a; 将变量声明在方法内部&#xff08;局部变量&#xff09;&#xff0…...

OpenMCU(六):STM32F103开发板功能介绍

概述 距上一篇关于STM32F103的FreeRTOS博客的发布已经过去很长时间没有更新了。在这段时间内&#xff0c;大家可以看到博主发表了一系列的关于使用qemu 模拟实现STM32F103的博客&#xff0c;博主本来想借助qemu开发stm32F103相关的一些软件功能&#xff0c;博主开发出来并成功运…...

运用数组和矩阵对数据进行存取和运算——NumPy模块 之五

目录 NumPy模块介绍 3.5.1 NumPy 操纵数组元素的逻辑 3.5.2 添加数组元素操作 1. append() 函数 2. insert() 函数 3.5.3 删除数组元素的操作 delete() 函数 3.5.4 数组元素缺失情况的处理 isnan() 函数 3.5.5 处理数组中元素重复情况 unique() 函数 3.5.6 拼接数组操作 1. con…...

AI Agent开发第64课-DIFY和企业现有系统结合实现高可配置的智能零售AI Agent

开篇 我们之前花了将近10个篇章讲Dify的一些基础应用,包括在讲Dify之前我们讲到了几十个AI Agent的开发例子,我不知道大家发觉了没有,在AI Agent开发过程中我们经常会伴随着这样的一些问题: 需要经常改猫娘;需要经常改调用LLM的参数,甚至在一个流程中有3个节点,每个节点…...

日志 Slf4j , Java 中使用

// 示例代码package biz.baijing.controller;import biz.baijing.pojo.Result; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.w…...

Matlab 单机无穷大系统故障

1、内容简介 Matlab 236-单机无穷大系统故障 可以交流、咨询、答疑 2、内容说明 略 摘要&#xff1a;短路是电力系统中最容易发生的故障&#xff0c;每年因短路而引发的电气事故不计其数。本文详细介绍了短路故障产生的原因以及危害等&#xff0c;并重点介绍了Simulink仿真工…...

Hadoop区别

Hadoop • 定义 • Hadoop是一个由Apache基金会开发的分布式计算平台。它主要包括HDFS&#xff08;Hadoop Distributed File System&#xff09;和MapReduce编程模型。HDFS用于存储大规模数据&#xff0c;它将文件分割成多个数据块&#xff08;block&#xff09;&#xff0c;并…...

【软件工程】软件缺陷 基于组合的优化方法

在软件缺陷检测中&#xff0c;基于组合的优化方法主要通过数学和计算策略高效地探索可能的解空间&#xff0c;以解决测试用例生成、缺陷定位和预测等问题。以下是其关键要点和应用场景的整理&#xff1a; 1. 组合优化在软件缺陷检测中的应用场景 测试用例生成 组合测试&#xf…...

python opencv 将不同shape尺寸的图片制作video视频

python opencv 将不同shape尺寸的图片制作video视频。 具体代码实现如下&#xff1a; import os import cv2 import time import shutil def resize_img_keep_ratio(img, target_size):old_size img.shape[:2] # 原始图像大小ratio min(target_size[i] / old_size[i] for …...

Open CASCADE学习|由大量Edge构建闭合Wire:有序与无序处理的完整解析

在CAD建模中,构建闭合的Wire(线框)是拓扑结构生成的基础操作。OpenCascade(OCCT)作为强大的几何建模库,支持从离散的Edge(边)构建Wire,但在实际应用中,边的有序性直接影响构建的成功率。本文将详细探讨有序与无序两种场景下的实现方法,并提供完整代码示例。 一、有序…...

在IDEA中导入gitee项目

一、导入前准备工作 1、下载gitee插件 2、下载好之后就能在VCS中找到share Project on gitee。 二、导入 1、回到idea主页面 2、可以授权登录绑定gitee账号&#xff0c;就可以直接打开仓库。&#xff08;条件是这个是要打开自己仓库里的代码&#xff09; 3、也可以复制看见的…...

Edge Remover v18.7 绿色版:轻松卸载 Edge 浏览器,彻底清理残留数据

Edge Remover 是一款专门用于卸载 Microsoft Edge 浏览器及其 WebView2 运行时的工具。它能够彻底删除 Edge 浏览器及其相关组件&#xff0c;包括所有文件、注册表项和其他残留数据。此外&#xff0c;Edge Remover 还可以防止 Windows 更新自动重新安装 Edge 浏览器。 软件功能…...

深入理解 iOS 开发中的 `use_frameworks!`

在使用 CocoaPods 管理 iOS 项目依赖时&#xff0c;开发者经常会在 Podfile 文件中看到一个配置选项&#xff1a;use_frameworks!。本文将详细介绍这个配置选项的含义&#xff0c;以及如何决定是否在项目中使用它。 一、什么是 use_frameworks! 在 CocoaPods 中引入第三方库时…...

Vue学习百日计划-Gemini版

核心理念&#xff1a; 基础先行&#xff1a; HTML, CSS, JavaScript 是前端的基石&#xff0c;必须扎实。聚焦 Vue 3&#xff1a; 学习当前主流的 Vue 3 版本&#xff0c;重点掌握 Composition API。实践驱动&#xff1a; 每个阶段都要有项目练习&#xff0c;理论结合实践。生…...

不定长滑动窗口---初阶篇

目录 引言 求最长/最大 3. 无重复字符的最长子串 3090. 每个字符最多出现两次的最长子字符串 1493. 删掉一个元素以后全为 1 的最长子数组 1208. 尽可能使字符串相等 904. 水果成篮 1695. 删除子数组的最大得分 2958. 最多 K 个重复元素的最长子数组 2024. 考试的最大…...

MacOS 上构建 gem5

MacOS 中只存在 python3&#xff0c;但是scons 只认 python&#xff0c;不在 系统中创建 软连接&#xff0c;一个是因为比较难操作&#xff1b;另一个是尽量不要更改系统。所以独立构件python 和scons&#xff1a; 1&#xff0c;安装python 下载源代码&#xff1a; Python S…...

矩阵置零算法讲解

矩阵置零算法讲解 一、问题描述 给定一个 (m \times n) 的矩阵,如果一个元素为 (0) ,则将其所在行和列的所有元素都设为 (0) 。要求使用原地算法,即在不使用额外矩阵空间的情况下完成操作。 二、解题思路 暴力解法 最直观的想法是遍历矩阵,当遇到 (0) 元素时,直接将其…...

HAProxy + Keepalived + Nginx 高可用负载均衡系统

1. 项目背景 在现代Web应用中&#xff0c;高可用性和负载均衡是两个至关重要的需求。本项目旨在通过HAProxy实现流量分发&#xff0c;通过Keepalived实现高可用性&#xff0c;通过Nginx提供后端服务。该架构能够确保在单点故障的情况下&#xff0c;系统仍然能够正常运行&#…...

火山RTC 6 自定义视频

文档&#xff1a; 自定义视频采集--实时音视频-火山引擎 这个点&#xff0c;相关的文档 关于PC上的资料只有寥寥几句&#xff0c;没有代码、没有DEMO&#xff0c;自己琢磨了几天&#xff0c;没走对方向&#xff0c;和客服你来我往拉锯了几天加投诉下&#xff0c;才给了点内部…...

[Java][Leetcode middle] 121. 买卖股票的最佳时机

暴力循环 总是以最低的价格买入&#xff0c;以最高的价格卖出: 例如第一天买入&#xff0c;去找剩下n-1天的最高价格&#xff0c;计算利润 依次计算到n-1天买入&#xff1b; 比较上述利润 // 运行时间超时。 o(n^2)public int maxProfit1(int[] prices) {int profit 0;for (i…...

《数据结构初阶》【堆 + 堆排序 + TOP-K】

【堆 堆排序 TOP-K】目录 前言&#xff1a;什么是堆&#xff1f;堆的实现方式有哪些&#xff1f;我们要选择哪种方式进行实现&#xff1f; ----------------堆的实现----------------什么是向上调整算法&#xff0c;要怎么实现&#xff1f;什么是向下调整算法&#xff0c;要怎…...

sqlilab-Less-18

知识铺垫 User-Agent 首部包含了一个特征字符串&#xff0c;用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。user-agent的作用。通过识别用户身份&#xff0c;响应合适的web界面&#xff0c;所以更改可以让电脑返回一个手机界…...

mapbox进阶,使用mapbox-plugins插件加载饼状图

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.1 ☘️mapboxgl.Map style属性二、🍀使用mapbox-plugins插件加载饼状图1. ☘…...

【Java继承】——面向对象编程的基石

&#x1f381;个人主页&#xff1a;User_芊芊君子 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 &#x1f50d;系列专栏&#xff1a;【Java】内容概括 【前言】 在Java面向对象编程中&#xff0c;继承是一个非常重要的概念。它允许我们创建一个新类&…...

【数据结构】——队列

一、队列的概念和结构 概念&#xff1a; 只允许在⼀端进⾏插⼊数据操作&#xff0c;在另⼀端进⾏删除数据操作的特殊线性表&#xff0c;队列具有先进先 出FIFO(First In First Out)。 入队&#xff1a;进行数据插入的一端叫做队尾 出队&#xff1a;进行删除操作的一端叫做队…...

如何找出所有不重复的三位偶数:详细解法与思考过程

问题描述 给定一个包含数字&#xff08;0-9&#xff09;的数组digits&#xff0c;其中可能包含重复元素。我们需要找出所有满足以下条件且互不相同的整数&#xff1a; 该整数由digits中的三个元素按任意顺序依次连接组成 该整数不含前导零&#xff08;即必须是100-999之间的数…...

每日Prompt:超现实交互场景

提示词 一幅铅笔素描画&#xff0c;描绘了 一个女孩 与 一朵玫瑰 互动的场景&#xff0c;其中 一朵玫瑰 以逼真的全彩风格呈现&#xff0c;与 一个女孩及背景的手绘素描风格形成超现实的对比。...