Shell指令
# Shell指令
# 基础
# 复合命令
在Shell脚本中,复合命令是由多个简单命令组合而成的命令,它们可以是管道(pipe),列表(list),条件语句(conditional),循环语句(loops),函数(functions)等。以下是一些常见的Shell复合命令类型:
管道(Pipe):
command1 | command2
1管道允许将一个命令的输出作为另一个命令的输入。
列表(List):
command1; command2
1列表允许你按顺序执行多个命令,每个命令在前一个命令完成后执行。
# 常用命令
ls -a -F # 显示所有文件,文件夹后面带/
cat test.txt -n # 输出文件内容并表明行号
mkdir -p /bin/test/a # 创建所有需要的目录
cp -r /bin/a /bin/b # 拷贝目录
mv docs/ bin/ a.txt dst/ # 将多个目录和文件移动到dst目录中
ls -l test.txt # 显示详细信息以判断文件类型,权限等
echo "aaa" # 输出文本
echo -e "aaa\n" # 使符号起作用
OUTPUT = "> out.file"
eval echo hello $OUTPUT # eval让Shell第二次重新处理命令行
expr 3+2 # 执行简单的整数算术运算
touch a.txt # 创建新文件
# 命令别名
alias lm='ls -al | more'
unalias lm # 取消别名
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
符号链:
# 创建指向文件的符号链:
ln -s target_file symlink_name
# 创建指向目录的符号链:
ln -s target_directory symlink_directory
# 例如在同一个文件夹下存在test1和test2,需要将test1中的文件链接到test2中:
ln -s ../test1/a.txt ./test2/b.txt
2
3
4
5
6
# find
Linux 中的 find
命令是一个非常强大的工具,用于在指定目录及其子目录下查找符合条件的文件或目录。以下是 find
命令的一些基本用法和选项:
基本语法:
find [path] [options] [actions]
1path
:指定搜索的起始目录,默认为当前目录(.
)。expression
:定义搜索条件。
常用选项:
-name
:按文件名查找文件。例如-name "*.txt"
查找所有以.txt
结尾的文件。-type
:查找文件类型,可以是f
(文件)、d
(目录)等。-size
:按文件大小查找文件,例如-size +10M
查找大于 10MB 的文件。-mtime
:按文件内容最后修改时间查找文件,单位是天。例如-mtime -7
查找过去 7 天内修改过的文件。-atime
:按文件最后访问时间查找文件。-ctime
:按文件状态最后改变时间查找文件。-user
:按文件所有者查找文件。-group
:按文件所属组查找文件。-mindepth
和--depth
:控制搜索的深度。-exec
:对找到的每个文件执行指定的命令。例如-exec rm {} \;
删除找到的每个文件。-print
:打印找到的文件名(默认行为)。-maxdepth
和-mindepth
:限制搜索的深度。
组合使用:
find
命令可以结合逻辑运算符来使用,如-o
(或)和-not
(非)。-o
:表示逻辑或,例如-name "*.txt" -o -name "*.pdf"
查找所有.txt
或.pdf
文件。-not
:表示逻辑非,例如-not -name "*.tmp"
查找所有非.tmp
文件。
使用正则表达式: 在某些版本的
find
中,可以使用-path
选项来使用正则表达式匹配路径。使用
find
命令的示例:- 查找当前目录及其子目录下所有
.txt
文件:find . -name "*.txt"
1 - 查找
/var/log
目录下 7 天内未修改的文件并删除:find /var/log -type f -mtime +7 -exec rm {} \;
1 - 查找
/home/user
目录下所有属于用户user
的文件:find /home/user -user user
1
- 查找当前目录及其子目录下所有
# xargs
xargs
能够读取标准输入(stdin)数据,将其转换为命令行参数,并执行相应的命令。xargs
常用于与管道(pipe)一起使用,将一个命令的输出作为另一个命令的输入。
以下是 xargs
的一些关键特性和选项:
基本用法:
command | xargs [options] [command]
1这里,
command
是生成输入数据的命令,xargs
读取这些数据,并将其作为参数传递给后面的command
。常用选项:
-0
或--null
:使用 null 字符作为输入项的分隔符,通常与find
命令的-print0
选项一起使用,适用于文件名包含空格或特殊字符的情况。-a
:从每个给定的文件中读取输入项,直到文件结束。-I {}
:指定替换字符串{}
,xargs
会用输入项替换{}
并执行命令。例如:输出将是:echo -e "one\ntwo" | xargs -I {} echo "Item: {}"
1Item: one Item: two
1
2-n [number]
或--max-args [number]
:指定每次调用命令时使用的最大参数数量,默认为每个命令一行。-P [number]
或--max-procs [number]
:指定同时运行的最大进程数。-p
:在执行命令前提示用户确认。--max-chars [number]
或-x
:指定每个命令行的最大字符数,超过这个数将自动换行。-r
:如果输入为空,则不执行命令。-t
:在执行命令之前打印命令和参数。
使用示例:
- 使用
find
和xargs
删除当前目录下所有.tmp
文件:find . -type f -name "*.tmp" -print0 | xargs -0 rm -f
1 - 将当前目录下所有
.txt
文件复制到/backup
目录:find . -type f -name "*.txt" | xargs -I {} cp {} /backup
1 - 并行执行
tar
压缩当前目录下所有.tar
文件,同时运行的最大进程数为 4:find . -type f -name "*.tar" | xargs -P 4 -I {} tar -czvf {}.tar.gz {}
1
- 使用
注意事项:
- 当使用
xargs
时,如果输入数据中包含特殊字符或空格,可能会引起问题。使用-0
和-print0
选项可以避免这类问题。 - 使用
-p
选项可以增加交互性,每次执行前都会提示用户确认。 - 使用
-n
选项可以控制每次调用命令时的参数数量,有助于防止命令行过长。
- 当使用
# 权限
以三个为一组,且均为『rwx』 的三个参数的组合。其中,[ r ]代表可读(read)、[ w ]代表可写(write)、[ x ]代表可执行(execute)。 要注意的是,这三个权限的位置不会改变,如果没有权限,就会出现减号[ - ]。
[!NOTE]
目录必须给到r和x才能切换到目录中去。
chgrp :改变档案所属群组
[root@study ~]# chgrp [-R] dirname/filename ... 选项与参数: -R : 进行递迴(recursive)的持续变更,亦即连同次目录下的所有档案、目录 都更新成为这个群组之意。常常用在变更某一目录内所有的档案之情况。 范例: [root@study ~]# chgrp users initial-setup-ks.cfg [root@study ~]# ls -l -rw-r--r--. 1 root users 1864 May 4 18:01 initial-setup-ks.cfg [root@study ~]# chgrp testing initial-setup-ks.cfg chgrp: invalid group: `testing' <== 发生错误讯息啰~找不到这个群组名~
1
2
3
4
5
6
7
8
9
10chown :改变档案拥有者
[root@study ~]# chown [-R] 帐号名称 档案或目录 [root@study ~]# chown [-R] 帐号名称:群组名称 档案或目录 选项与参数: -R : 进行递迴(recursive)的持续变更,亦即连同次目录下的所有档案都变更 范例:将 initial-setup-ks.cfg 的拥有者改为bin这个帐号: [root@study ~]# chown bin initial-setup-ks.cfg [root@study ~]# ls -l -rw-r--r--. 1 bin users 1864 May 4 18:01 initial-setup-ks.cfg 范例:将 initial-setup-ks.cfg 的拥有者与群组改回为root: [root@study ~]# chown root:root initial-setup-ks.cfg [root@study ~]# ls -l -rw-r--r--. 1 root root 1864 May 4 18:01 initial-setup-ks.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14chmod :改变档案的权限, SUID, SGID, SBIT等等的特性
使用数字类型,r:4,w:2,x:1
[root@study ~]# ls -al .bashrc -rw-r--r--. 1 root root 176 Dec 29 2013 .bashrc [root@study ~]# chmod 777 .bashrc [root@study ~]# ls -al .bashrc -rwxrwxrwx. 1 root root 176 Dec 29 2013 .bashrc
1
2
3
4
5符号类型改变档案权限
chmod u g o a +(加入) -(除去) =(设定) r w x 档案或目录 [root@study ~]# chmod u=rwx,go=rx .bashrc [root@study ~]# chmod a+w .bashrc
1
2
# 重定向
# 使用符号 2>&1 将标准错误(stderr)重定向到标准输出(stdout)。
command 2>&1 output.txt
command > output.txt 2>&1
2
3
# 进程
long_running_process &
这会将 long_running_process
放入后台执行,Shell会立即显示新的提示符。
使用ctrl + z
将前台程序悬挂,然后使用bg %1
将其移入后台,实用fg %1
将其移入前台。
使用jobs
显示悬挂的进程或者后台进程。使用ps -f
显示当前终端进程,使用ps -e
显示所有进程。
使用ps aux
显示所有进程的详细信息。
使用top
显示实时进程
例子:
ps aux | grep rosbag/record | grep -v grep | awk '{print $2}' | xargs kill -SIGINT
kill
命令用于发送信号给进程,-SIGINT
选项指定发送SIGINT
信号,这通常是Ctrl+C的信号,用于请求进程优雅地终止。pgrep python | xargs kill -2
:pgrep
命令用于搜索当前运行的进程列表,并根据指定的条件列出匹配的进程的进程ID(PID),-2用于ctrl+c终止
# 变量
# 标准的变量引用
echo $HOME
# 使用花括号,即使变量为空,也不会报错
echo ${HOME}
# 使用花括号提供默认值
echo ${HOME:-"/default/home/directory"}
# 双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
『var="lang is $LANG"』则『echo $var』可得『lang is en_US』
# 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』
# 取消变量
unset var
# 累加变量
PATH=${PATH}:/home/dmtsai/bin
# 查看所有环境变量
env
# 所有变量
set
# 显示当前进程PID,$变量表征
echo $$
# 上一个运行的命令所回传的值,?表示回传值
echo $?
# 表示所有传递给脚本或命令的参数
echo $*
# 表示传递给脚本或命令的参数个数
echo $#
# 将自定义变量变成环境变量
export 变量名称
# 双括号可直接使用变量,且执行算数运算
echo $((a+b)) # 输出加和3
((a = 5 < 10 && 10 > 1))
echo a
# 定义类型
[root@www ~]# declare [-aixr] variable
选项与参数:
-a :将后面名为 variable 的变量定义成为数组 (array) 类型
-i :将后面名为 variable 的变量定义成为整数数字 (integer) 类型
-x :用法与 export 一样,就是将后面的 variable 变成环境变量;
-r :将变量配置成为 readonly 类型,该变量不可被更改内容,也不能 unset
范例一:让变量 sum 进行 100+300+50 的加总结果
[root@www ~]# sum=100+300+50
[root@www ~]# echo $sum
100+300+50 <==咦!怎么没有帮我计算加总?因为这是文字型态的变量属性啊!
[root@www ~]# declare -i sum=100+300+50
[root@www ~]# echo $sum
450
范例二:将 sum 变成环境变量
[root@www ~]# declare -x sum
[root@www ~]# export | grep sum
declare -ix sum="450" <==果然出现了!包括有 i 与 x 的宣告!
范例三:让 sum 变成只读属性,不可更动!
[root@www ~]# declare -r sum
[root@www ~]# sum=tesgting
-bash: sum: readonly variable <==老天爷~不能改这个变量了!
范例四:让 sum 变成非环境变量的自定义变量吧!
[root@www ~]# declare +x sum <== 将 - 变成 + 可以进行『取消』动作
[root@www ~]# declare -p sum <== -p 可以单独列出变量的类型
declare -ir sum="450" <== 看吧!只剩下 i, r 的类型,不具有 x 啰!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Shell Scripts
[!TIP]
利用直接运行(sh xxx.sh)的方式来运行 script和利用 source 来运行结果不同。前者是在子程序中运行,因此子程序中的变量在父程序中不存在,而后者完全在父程序中运行。
# if else
if [[ ! "$algorithmType" =~ "fusion" ]];then
type_pre='lidar' # 使用正则判断
fi
if [ "$algorithmType" == "prediction" ]; then
2
3
4
# function
add_numbers() {
echo $(( $1 + $2 ))
}
# 调用函数
result=$(add_numbers 3 5)
echo "Result is $result"
2
3
4
5
6
7
# while
while [ condition ] <==中括号内的状态就是判断式
do <==do 是回圈的开始!
程序段落
done <==done 是回圈的结束
until [ condition ]
do
程序段落
done
2
3
4
5
6
7
8
9
10
for
for var in con1 con2 con3 ...
do
程序段
done
for (( i=1; i<=$nu; i=i+1 ))
do
s=$(($s+$i))
done
echo "The result of '1+2+3+...+$nu' is ==> $s"
2
3
4
5
6
7
8
9
10
# 文本处理
head -n # 输出前n行
tail -n # 输出后n行
ls -1ut # 输出当前文件夹下的所有东西,分行显示,同时按照时间修改排序。-u表示以最新为首,无则反之。-t表示按时间修改。
tail -f # 强制查看,能够看到被写入的文件比如log
2
3
4
# 通配符
符号 | 意义 |
---|---|
* | 代表『 0 个到无穷多个』任意字符 |
? | 代表『一定有一个』任意字符 |
[ ] | 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b, c, d 这四个任何一个』 |
[ - ] | 若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的! |
[^ ] | 若中括号内的第一个字符为指数符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,只要是非 a, b, c 的其他字符就接受的意思。 |
接下来让我们利用通配符来玩些东西吧!首先,利用通配符配合 ls 找檔名看看:
[root@www ~]# LANG=C <==由于与编码有关,先配置语系一下
范例一:找出 /etc/ 底下以 cron 为开头的档名
[root@www ~]# ll -d /etc/cron* <==加上 -d 是为了仅显示目录而已
范例二:找出 /etc/ 底下文件名『刚好是五个字母』的文件名
[root@www ~]# ll -d /etc/????? <==由于 ? 一定有一个,所以五个 ? 就对了
范例三:找出 /etc/ 底下文件名含有数字的文件名
[root@www ~]# ll -d /etc/*[0-9]* <==记得中括号左右两边均需 *
范例四:找出 /etc/ 底下,档名开头非为小写字母的文件名:
[root@www ~]# ll -d /etc/[^a-z]* <==注意中括号左边没有 *
范例五:将范例四找到的文件复制到 /tmp 中
[root@www ~]# cp -a /etc/[^a-z]* /tmp
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
除了通配符之外,bash 环境中的特殊符号有哪些呢?底下我们先汇整一下:
符号 | 内容 |
---|---|
# | 批注符号:这个最常被使用在 script 当中,视为说明!在后的数据均不运行 |
\ | 跳脱符号:将『特殊字符或通配符』还原成一般字符 |
| | 管线 (pipe):分隔两个管线命令的界定(后两节介绍); |
; | 连续命令下达分隔符:连续性命令的界定 (注意!与管线命令并不相同) |
~ | 用户的家目录 |
$ | 取用变量前导符:亦即是变量之前需要加的变量取代值 |
& | 工作控制 (job control):将命令变成背景下工作 |
! | 逻辑运算意义上的『非』 not 的意思! |
/ | 目录符号:路径分隔的符号 |
>, >> | 数据流重导向:输出导向,分别是『取代』与『累加』 |
<, << | 数据流重导向:输入导向 (这两个留待下节介绍) |
' ' | 单引号,不具有变量置换的功能 |
" " | 具有变量置换的功能! |
| 两个『 ` 』中间为可以先运行的命令,亦可使用 $( ) |
( ) | 在中间为子 shell 的起始与结束 |
{ } | 在中间为命令区块的组合! |
# cut
[dmtsai@study ~]$ cut -d'分隔字元' -f fields <==用于有特定分隔字元
[dmtsai@study ~]$ cut -c 字元区间 <==用于排列整齐的讯息
选项与参数:
-d :后面接分隔字元。与 -f 一起使用;
-f :依据 -d 的分隔字元将一段讯息分割成为数段,用 -f 取出第几段的意思;
-c :以字元 (characters) 的单位取出固定字元区间;
范例一:将 PATH 变数取出,我要找出第五个路径。
[dmtsai@study ~]$ echo ${PATH}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 1 | 2 | 3 | 4 | 5 | 6 |
[dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 5
# 如同上面的数字显示,我们是以『 : 』作为分隔,因此会出现 /home/dmtsai/.local/bin
# 那么如果想要列出第 3 与第 5 呢?,就是这样:
[dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 3,5
范例二:将 export 输出的讯息,取得第 12 字元以后的所有字串
[dmtsai@study ~]$ export
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/home/dmtsai"
declare -x HOSTNAME="study.centos.vbird"
.....(其他省略).....
# 注意看,每个资料都是排列整齐的输出!如果我们不想要『 declare -x 』时,就得这么做:
[dmtsai@study ~]$ export | cut -c 12-
HISTCONTROL="ignoredups"
HISTSIZE="1000"
HOME="/home/dmtsai"
HOSTNAME="study.centos.vbird"
.....(其他省略).....
# 知道怎么回事了吧?用 -c 可以处理比较具有格式的输出资料!
# 我们还可以指定某个范围的值,例如第 12-20 的字元,就是 cut -c 12-20 等等!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# grep
grep
是一个强大的文本搜索工具,用于在文件中搜索匹配特定模式的行。以下是 grep
命令的一些关键特性和用法:
# 基本用法
grep pattern [file...]
:在指定的文件中搜索包含pattern
的行。
选项:
-i
:忽略大小写。搜索时不区分大写和小写字母。-v
:反向搜索。只打印不匹配pattern
的行。-r
或--recursive
:递归地在所有文件和目录中搜索。-l
:只打印包含匹配行的文件名。-n
:显示匹配行的行号。-c
:仅显示匹配行的数量,不显示行本身。--color
:将匹配的文本高亮显示(通常是彩色的)。-e
:使用多个搜索模式。-w
或--word-regexp
:仅匹配整个单词。--line-buffered
:使用行缓冲,确保输出即时显示,即使输出被管道传输。
# 示例
- 搜索包含 "error" 的行:
grep "error" logfile.txt
1 - 忽略大小写搜索 "error":
grep -i "error" logfile.txt
1 - 打印不包含 "error" 的行:
grep -v "error" logfile.txt
1 - 递归搜索目录中的所有文件:
grep -r "pattern" /path/to/directory
1 - 只打印包含 "error" 的文件名:
grep -l "error" /path/to/directory
1 - 显示匹配行的行号:
grep -n "error" logfile.txt
1 - 显示匹配行的数量:
grep -c "error" logfile.txt
1 - 高亮显示匹配的文本:
grep --color "error" logfile.txt
1 - 使用多个搜索模式:
grep -e "error" -e "warning" logfile.txt
1 - 仅匹配整个单词 "error":
grep -w "error" logfile.txt
1
# 正则表达式
grep
支持基本的正则表达式,允许进行更复杂的搜索模式匹配。例如:
- 搜索以 "log" 开头的行:
grep "^log" logfile.txt
1 - 搜索包含数字的行:
grep "[0-9]" logfile.txt
1
# 管道使用
grep
经常与其他命令结合使用,通过管道传递数据。例如,使用 cat
查看文件并搜索包含特定文本的行:
cat largefile.txt | grep "pattern"
# 注意事项
- 默认情况下,
grep
区分大小写,除非你使用-i
选项。 - 使用复杂的正则表达式时,可能需要根据Shell的不同使用引号或转义字符。
- 在某些系统中,
grep
的默认行为可能因版本或配置而异,例如,是否默认启用颜色输出。
# sed
sed
(Stream Editor)是一个功能强大的Unix-like命令行工具,用于对文本数据进行过滤和替换。以下是 sed
的一些基本用法和概念:
# 基础构造,script为具体模型和动作,如/pattern/action,表示在pattern下搜索到时的动作。files表示一个或多个文件。
sed 'script' files
2
sed
的基本语法如下:
sed [选项] '指令' 文件
其中,[选项]
是可选的,[指令]
是必需的,文件
是要处理的文本文件。
# 常用指令
s
:替换指令,用于替换文本。d
:删除指令,用于删除匹配的行。p
:打印匹配成功的行
# 常用选项
-n
:仅打印经过sed
处理的行。-e
:允许在命令行上执行多个sed
命令,例如:sed -e 'script1' -e 'script2'
.-i
:直接修改文件内容,而不是输出到标准输出,例如:sed -i 's/old/new/g' filename
。
# 替换指令(s)
替换指令的基本格式如下:
s/old/new/
这将把所有的 "old" 替换为 "new"。使用 g
标志可以实现全局替换:
s/old/new/g
[!IMPORTANT]
在
s
命令中可以使用&
在new中重用old中的匹配结果:sed 's/ab/$ab/g' test.txt
# 打印指令(p)
会打印出所有的行和匹配的结果,使用-n只输出匹配结果
/pattern/p
# 删除指令(d)
删除指令可以删除匹配特定模式的行:
/pattern/d
# 插入和追加指令(i 和 a)
插入和追加指令可以在指定模式匹配的行之前或之后添加文本:
i\
这是插入的文本
a\
这是追加的文本
2
3
4
注意:在 i
和 a
指令后面需要使用 \
来表示多行文本。
# 模式匹配
sed
支持基本的正则表达式进行模式匹配。例如:
s/[0-9]+/数字/g
这将把所有的数字替换为 "数字"。
# 实例
- 将文件中的 "old" 替换为 "new" 并输出结果:
sed 's/old/new/g' filename
1 - 直接在文件中替换文本(原地编辑):
sed -i 's/old/new/g' filename
1 - 删除包含 "error" 的所有行:
sed '/error/d' filename
1 - 在每行的末尾追加文本 " - append":
sed 's/$/ - append/' filename
1 - 在包含 "pattern" 的行后追加文本:
sed '/pattern/a\ 这是追加的文本' filename
1
2
# 多行模式
sed
可以处理多行模式,使用 \
来分隔多行:
sed '/start_pattern/{
/end_pattern/!d
}'
2
3
这将删除从 "start_pattern" 到 "end_pattern" 之间的所有行。
# awk
awk
是一个强大的文本处理工具,它设计用于处理结构化数据,特别是表格化数据。awk
的名称来源于它的创始人 Alfred V. Aho、Peter J. Weinberger 和 Brian W. Kernighan 的姓氏首字母。
# 基本语法
awk
的基本语法如下:
awk '/pattern/{action}' files
这里,条件
是可选的,如果省略则对所有行执行 动作
。
变量
$0
: 整行内容。$1
,$2
, ...: 当前行的第1个,第2个...字段(默认字段分隔符为空白字符)。例如:awk '{print $1,$3;}' fruit.txt
,其中的逗号会打印成空格。NF
: 当前行的字段总数。NR
: 已处理的记录数(行号)。
常用内置函数:
print
及printf
: 打印文本。sprintf
: 格式化字符串。split
: 将字符串分割成数组。length
: 返回字符串的长度。
常用选项:
-F
: 设置输入字段分隔符。-v
: 设置变量的值。
# 比较操作符
以下是一些使用 awk
比较操作符的示例:
检查字段是否等于特定值:
awk '$1 == "expected_value" { print "Match found" }' data.txt
1检查数值字段是否在某个范围内:
awk '$1 >= 10 && $1 <= 20 { print "Value is within range" }' data.txt
1使用正则表达式检查字段是否匹配模式:
awk '$1 ~ /^[0-9]+$/ { print "Field contains only digits" }' data.txt
1检查字段是否不匹配模式:
awk '$1 !~ /^[a-z]+$/ { print "Field contains non-lowercase letters" }' data.txt
1
使用next跳过后续检查项:
awk ' $1 == "expected_value" { print "Match 1 found";next; } $2 == "expected_value" { print "Match 2 found" } ' data.txt
1
2
3
4
# 脚本示例
awk -F, '{
if ($1 == "条件") print $2
}' filename.csv
2
3
这个脚本将处理 filename.csv
文件,该文件的字段由逗号分隔。如果第一字段匹配 "条件",则打印第二字段。
# 复杂脚本示例
awk '{ sum += $3 }
END {
if (NR > 0) print "Average:", sum / NR
}' filename
2
3
4
这个脚本将计算文件中第三字段的平均值,并在处理完所有行后打印出来。
# 模式匹配
- 使用模式匹配特定行:
awk '/pattern/ {print $0}' filename
1 - 使用多个模式:
awk '模式1 {动作1} 模式2 {动作2}' filename
1
# 内置数组
awk
允许你使用内置数组来存储和操作数据:
awk '{ arr[$1] += $2 } END { for (key in arr) print key, arr[key] }' filename
这个脚本将创建一个数组 arr
,其中键是第一字段,值是第二字段的累加和。
# 流程控制
awk
支持 if-else
和 while
等流程控制语句:
awk '{ if ($1 > 0) print "Positive"; else print "Non-positive" }' filename
# 多文件处理
awk
可以同时处理多个文件:
awk '{ ... }' file1 file2 file3
awk
的强大之处在于其灵活性和对复杂数据处理的支持。它可以读取、处理和生成结构化文本数据,是Unix-like系统中不可或缺的工具之一。