awk命令

文章目录

  • awk命令
    • 一、awk概述
      • 1、awk概述
      • 2、关于awk
        • 2.1 工作原理
        • 2.2 命令格式
          • 选项
          • 常见内置变量
    • 二、awk用法
      • 1、基础用法
        • 1.1 打印所有内容
        • 1.2 打印行的内容及行号
        • 1.3 打印指定行和指定行的范围
        • 1.4 打印文本过滤匹配的内容
        • 1.5 打印奇偶数行
          • 奇偶行打印特殊方式--getline
      • 2、BEGIN打印模式
      • 3、字段处理
        • 3.1 指定分隔符打印
        • 3.2 条件判断打印
          • 正向判断打印
          • 判断取反打印
          • if语句判断打印
        • 3.3 提取特定字段
    • 三、awk的三元表达式
      • 1、java和shell中的三元表达式
      • 2、awk三元表达式的应用
    • 四、awk精准筛选
    • 五、内置变量的使用
      • 1、NR 显示行号
        • NR==n代表显示第n行
      • 2、NF 字段个数
      • 3、FS 输入时的列分隔符
      • 4、OFS 输出内容的列分隔符
      • 5、RS 指定分隔符
      • 6、FILENAME
    • 六、awk结合数组运用
      • 1、awk中定义数组打印
      • 2、去重打印数组
    • 七、关系表达式

awk命令

一、awk概述

awk将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。

1、awk概述

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作数据可以来自标准输入也可以是管道或文件。

20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk

之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

2、关于awk

2.1 工作原理
  • 当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出

  • 如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次

  • 默认情况下字段的分隔符为空格或tab键,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。

  • sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个""字段"然后再进行处理。awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。

  • 在使用awk命令的过程中,可以使用逻辑操作符"&&“表示"与”、“||“表示"或”、”!“表示"非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。

  • awk 后面接两个单引号并加上大括号{ }来设置想要对数据进行的处理操作,awk 可以处理后续接的文件,也可以读取来自前个命令的标准输出。

2.2 命令格式
awk [options]   'program' var=value   file…

awk [选项]   '模式条件' 文件1 文件2...

注意事项

  • 一定是单引号: ‘模式或条件{操作}’
  • {}外指定条件,{}内指定操作
  • 内建变量不能使用双引号括起来,不然系统会把它当成字符串
选项
选项 说明
-v 定义变量
-F 指定分隔符
常见内置变量
内置变量 说明
NR 当前处理的行的行号(序数)
NF 当前处理的行的字段个数
FS 列分隔符,指定每行文本的字段分隔符,默认为空格或制表位。 与 “ -F ” 作用相同
OFS 输出内容的列分隔符
RS 行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n"
$0 当前处理的行的整行内容
$n 当前处理行的第n个字段(第n列)
FILENAME 被处理的文件名

二、awk用法

1、基础用法

1.1 打印所有内容
#打印所有内容
[root@localhost data]#awk '{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin

awk命令_第1张图片

1.2 打印行的内容及行号
#打印行的内容及行号
[root@localhost data]#awk '{print NR,$0}' /etc/passwd
#NR表示打印行号;$0表示打印所有内容
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
11 games:x:12:100:games:/usr/games:/sbin/nologin
12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13 nobody:x:99:99:Nobody:/:/sbin/nologin
14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
15 dbus:x:81:81:System message bus:/:/sbin/nologin
16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
17 abrt:x:173:173::/etc/abrt:/sbin/nologin
18 libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
19 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
20 colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
21 saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
22 rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin

awk命令_第2张图片

1.3 打印指定行和指定行的范围
#打印第2行内容
[root@localhost data]#awk 'NR==2{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin

#打印第2行至第6行的内容
[root@localhost data]#awk 'NR==2,NR==6{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync

#打印第2行至第6行的内容
[root@localhost ~]#awk 'NR>=2&&NR<=6{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync

awk命令_第3张图片

1.4 打印文本过滤匹配的内容
#匹配文件中以root开头的行
[root@localhost data]#awk '/^root/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

#匹配文件中以bash结尾的行
[root@localhost data]#awk '/bash$/{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash

awk命令_第4张图片

1.5 打印奇偶数行
#打印偶数行
[root@localhost ~]#awk 'NR%2==0{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
halt:x:7:0:halt:/sbin:/sbin/halt
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
libstoragemgmt:x:998:996:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
chrony:x:995:991::/var/lib/chrony:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
geoclue:x:994:989:User for geoclue:/var/lib/geoclue:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
sssd:x:992:987:User for sssd:/:/sbin/nologin
gnome-initial-setup:x:991:986::/run/gnome-initial-setup/:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin

#打印奇数行 
[root@localhost ~]#awk 'NR%2==1{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
saslauth:x:996:76:Saslauthd user:/run/saslauthd:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
qemu:x:107:107:qemu user:/:/sbin/nologin
setroubleshoot:x:993:988::/var/lib/setroubleshoot:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash
zhangsan:x:1001:1001::/home/zhangsan:/bin/bash

awk命令_第5张图片

奇偶行打印特殊方式–getline

getline工作过程:

1)当getline左右无重定向符号(“<”)或者管道符号(“|”)时,awk首先读取的是第一行,而getline获取的是光标跳转至下一行的内容(也就是第二行)
原因:getline运行之后awk会改变NF,NR,$0,FNR等内部变量,所以此时读取$0的行号不再为1,而是2。

注意:
FNR:awk当前读取的记录数,其变量值小于等于NR,(比如说当读取完第一个文件后,读取第二个文件,FNR是会从0开始进行,而NR不会)。因此读取两个或两个以上的文件,NR==FNR,可以判断是不是在读取第一个文件。

2)当getline左右有管道符号或重定向符时,getline则作用定向输入文件,由于文件是刚打开,并没有被awk读入一行,而只是getline读入,所以getline返回的是文件的第一行,而不是跳转至一行输入
#打印偶数行
[root@localhost ~]#seq 10 |awk '{getline;print $0}'
2
4
6
8
10
##先进行getline跳转至下一行,awk读取跳转后的整行内容,经过逐步跳转读取,形成了只显示偶数行

#打印奇数行
[root@localhost etc]#seq 10 |awk '{print $0;getline}'
[root@localhost ~]#seq 10 |awk '{print $0;getline}'
1
3
5
7
9
##先进行awk打印第一行的内容,结束后按照正常顺序打印,但是getline进行跳转,第二行不打印了,最终呈现出奇数行打印

awk命令_第6张图片

2、BEGIN打印模式

格式:awk ‘BEGIN{…};{…};END{…}’ 文件

处理过程

  • 在 awk 处理指定的文本之前,需要先执行 BEGIN{…} 模式里的命令操作

  • 中间的 {…} 是真正用于处理文件的命令操作

  • 在 awk 处理完文件后才会执行 END{…}模式里的命令操作。END{ } 语句块中,往往会放入打印结果等语句。

3、字段处理

3.1 指定分隔符打印
#以冒号为分隔符,取第一列
[root@localhost data]#awk -F ':' '{print $1}' /etc/passwd |head
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator

awk命令_第7张图片

3.2 条件判断打印
正向判断打印
#提取uid号大于等于1000的用户
[root@localhost data]#awk -F: '$3>=1000{print $3,$1}' /etc/passwd
65534 nfsnobody
1000 liuyanfen
1001 zhangsan
 
##先用-F指定分隔符为":" ,文件以":"分割的第三列为uid,uid大于1000的打印第三列和第一列,也就是uid和用户

image-20240207142149233

判断取反打印
#提取uid号大于1000的用户
[root@localhost data]#awk -F: '!($3<=1000){print $3,$1}' /etc/passwd
65534 nfsnobody
1001 zhangsan

image-20240207142405692

if语句判断打印
#用if语句提取uid号大于等于1000的用户
[root@localhost data]#awk -F: '{if($3>=1000){print $3,$1}}' /etc/passwd
65534 nfsnobody
1000 liuyanfen
1001 zhangsan

image-20240207142736959

3.3 提取特定字段
#提取磁盘已经使用量
[root@localhost data]#df|awk '{print $5}'|tail -n +2|tr -d %
10
0
0
1
0
4
1
1
100

#方法二:提取磁盘已经使用量
[root@localhost data]#df |awk -F"[ %]+" '{print $5}'|tail -n +2
##[ %] 一个字符,看到空格和%,都当作分隔符。 + 表示一个以上

#方法三:提取磁盘已经使用量
[root@localhost data]#df |awk -F"[[:space:]]+|%" '{print $5}'|tail -n +2

awk命令_第8张图片

[root@localhost data]#ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.11  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::53e9:a034:7de9:f2b9  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:42:0c:18  txqueuelen 1000  (Ethernet)
        RX packets 127333  bytes 173110407 (165.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 32293  bytes 2132652 (2.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

#提取ip地址
[root@localhost data]#ifconfig ens33|awk 'NR==2{print $2}'
192.168.10.11

awk命令_第9张图片

三、awk的三元表达式

1、java和shell中的三元表达式

java中

(条件表达式)?(A表达式或者值):(B表达式或者值)

解释

条件表达式成立(为真)时,会取冒号前面的值A。 - 条件表达式不成立(为假)时,会取冒号后面的值B。

shell中

[ 条件表达式 ] && A || B

解释

条件表达式成立(为真)时,会取||前面的值A。 - 条件表达式不成立(为假)时,会取||后面的值B。

2、awk三元表达式的应用

格式:awk ‘(条件表达式)?(A表达式或者值):(B表达式或者值)’

[root@localhost data]#awk -F: '{max=($3>=$4)?$3:$4;{print max,$0}}' /etc/passwd |sed -n '1,6p'
0 root:x:0:0:root:/root:/bin/bash
1 bin:x:1:1:bin:/bin:/sbin/nologin
2 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
7 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
5 sync:x:5:0:sync:/sbin:/bin/sync

#比较passwd文件中第三列和第四列的大小,取他们结果较大的值,赋于变量max 并且输出max及其所在行的全部内容

awk命令_第10张图片

四、awk精准筛选

筛选方法 说明
$n (><==) 用于对比数值
$n~“字符串” 代表第n个字段,包含某个字符串的作用
$n!~“字符串” 代表第n个字段,不好含某个字符串的作用
$n==“字符串” 代表第n个字段为某个字符串的作用
$n!=“字符串” 代表第n个字段不为某个字符串的作用
$NF 代表最后一个字段
[root@localhost data]#awk -F: '$7~"bash"{print $1,$NF}' /etc/passwd
root /bin/bash
liuyanfen /bin/bash
zhangsan /bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第7列字段中包含bash字符的行,打印每行的第1列和最后1列

[root@localhost data]#awk -F: '$7!~"nologin"{print $1,$NF}' /etc/passwd
root /bin/bash
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
liuyanfen /bin/bash
zhangsan /bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第7列字段中不包含nologin字符的行,打印每行的第1列和最后1列

[root@localhost data]#awk -F: '($6=="/home/liuyanfen")&&($7=="/bin/bash"){print $0}' /etc/passwd
liuyanfen:x:1000:1000:liuyanfen:/home/liuyanfen:/bin/bash
#提取/etc/passwd文件中,以冒号为分隔符,第6字段为/home/liuyanfen,第7字段为/bin/bash的行

awk命令_第11张图片

五、内置变量的使用

内置变量 说明
NR 当前处理的行的行号(序数)
NF 当前处理的行的字段个数
FS 列分隔符,指定每行文本的字段分隔符,默认为空格或制表位。 与 “ -F ” 作用相同
OFS 输出内容的列分隔符
RS 行分隔符,awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n"
$0 当前处理的行的整行内容
$n 当前处理行的第n个字段(第n列)
FILENAME 被处理的文件名
$NF 最后一段
$(NF-1) 倒数第二段

1、NR 显示行号

[root@localhost data]#awk -F: '{print NR}' /etc/passwd
1
2
3
4
5
6
#显示行号

[root@localhost data]#awk -F: '{print $1"\t"NR}' /etc/passwd
root    1
bin     2
daemon  3
adm     4
lp      5
sync    6
#制表符

[root@localhost data]#awk -F: '{print NR"\t"$1}' /etc/passwd
1       root
2       bin
3       daemon
4       adm
5       lp
6       sync
#NR在前面时,行号数字显示在前

awk命令_第12张图片

NR==n代表显示第n行
[root@localhost data]#awk -F: 'NR==2{print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
#显示/etc/passwd文件的第2行

[root@localhost ~]#awk 'NR%2==0{print}' /etc/passwd
#打印偶数行

[root@localhost ~]#awk 'NR%2==1{print}' /etc/passwd
#打印奇数行


[root@localhost data]#awk -F: 'NR==2,NR==6 {print}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
#显示第2行至第6行的内容

awk命令_第13张图片

2、NF 字段个数

#显示前10行中每行有几个字段
[root@localhost data]#awk -F: '{print NF}' /etc/passwd |head
7
7
7
7
7
7
7
7
7
7

#显示前10行中每一行的最后一列
[root@localhost data]#awk -F: '{print $NF}' /etc/passwd |head
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
/bin/sync
/sbin/shutdown
/sbin/halt
/sbin/nologin
/sbin/nologin

#显示前10行中每一行的倒数第2列
[root@localhost data]#awk -F: '{print $(NF-1)}' /etc/passwd |head
/root
/bin
/sbin
/var/adm
/var/spool/lpd
/sbin
/sbin
/sbin
/var/spool/mail
/root

awk命令_第14张图片

3、FS 输入时的列分隔符

[root@localhost data]#awk -v FS=: '{print $1FS$3}' /etc/passwd|head
root:0
bin:1
daemon:2
adm:3
lp:4
sync:5
shutdown:6
halt:7
mail:8
operator:11

awk命令_第15张图片

4、OFS 输出内容的列分隔符

[root@localhost data]#echo A B C D |awk '{OFS="|";print $0;$1=$1;print $0}'
A B C D
A|B|C|D
#$1=$1是激活$0的重新赋值

image-20240207164907129

5、RS 指定分隔符

awk 从文件中读取资料时,将根据 RS 的定义把资料切割成许多条记录, 而 awk 一次仅读入一条记录进行处理。内置变量 RS 的预设值是"\n"。

但是也可以在使用 BEGIN 模式在操作前进行行分隔符的改变。

[root@localhost data]#echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost data]#
[root@localhost data]#echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin
#通过BEGIN模式在awk命令执行前将分隔符改为":",然后打印行号及每一行内容

awk命令_第16张图片

6、FILENAME

[root@localhost data]#awk -F: 'NR==2{print FILENAME}' /etc/passwd
/etc/passwd
#显示当前处理文件的名字

image-20240207170004821

六、awk结合数组运用

1、awk中定义数组打印

[root@localhost data]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}'
10

[root@localhost data]#awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[1]}'
20

awk命令_第17张图片

2、去重打印数组

[root@localhost ~]#q=(10 10 10 20 30 20 30 20 40 10 30 10)
[root@localhost ~]#echo ${q[@]}|awk -v RS=' ' '!a[$1]++'
10
20
30
40

awk命令_第18张图片

七、关系表达式

关系表达式结果为“真”才会被处理

真:结果为非0值,非空字符串

假:结果为空字符串或0值

[root@localhost data]#seq 10 |awk 0
[root@localhost data]#
[root@localhost data]#seq 10 |awk 1
1
2
3
4
5
6
7
8
9
10
[root@localhost data]#seq 10 |awk 2
1
2
3
4
5
6
7
8
9
10

awk命令_第19张图片

你可能感兴趣的:(运维,linux)