Linux 正则表达式
环境示例
[yuxb@controller ~ 15:21:42]$ cat words cat category acat concatenate dog
words
文件包含一些单词,用于测试正则表达式。
普通字符匹配
最简单的匹配方式:直接找文件里有 完全相同的文本。
[yuxb@controller lab 15:22:46]$ cat words | grep 'cat' cat category acat concatenate
解释:
-
grep 'cat'
→ 查找包含cat
的行 -
输出的每行都包含
cat
,不管它前面或后面还有什么字符。
字符集匹配
方括号 [...]
方括号表示 匹配其中任意一个字符。
[yuxb@controller lab 15:22:57]$ echo cbt >> words [yuxb@controller lab 15:23:39]$ echo c1t >> words [yuxb@controller lab 15:23:43]$ cat words | grep 'c[ab]t' cat category acat concatenate cbt
解释:
-
[ab]
→ 匹配 a 或 b -
'c[ab]t'
→ c + (a 或 b) + t -
只要符合规则的行都会被打印。
范围 [a-z] [A-Z] [0-9]
-
[a-z]
→ 匹配任意小写字母 -
[A-Z]
→ 匹配任意大写字母 -
[0-9]
→ 匹配任意数字
[yuxb@controller lab 15:23:48]$ cat words | grep 'c[a-z]t' cat category acat concatenate cbt [yuxb@controller lab 15:24:30]$ cat words | grep 'c[A-Z]t' cCt [yuxb@controller lab 15:24:34]$ cat words | grep 'c[0-9]t' c1t
组合使用:
[yuxb@controller lab 15:24:38]$ cat words | grep 'c[a-z0-9]t' cat category acat concatenate cbt c1t
⚠️ 注意:字符集中的
-
如果要匹配普通字符,要放在最前面或最后面。
[yuxb@controller lab 15:24:49]$ echo c-t >> words [yuxb@controller lab 15:25:10]$ cat words | grep 'c[-a-zA-Z0-9]t' cat category acat concatenate cbt c1t cCt c-t
取反 [^...]
^
放在方括号开头 → 匹配 不在里面的字符。
[yuxb@controller lab 15:25:39]$ cat words | grep 'c[^ab]t' c1t cCt c-t
解释:
-
[^ab]
→ 不是 a 或 b 的任意字符 -
'c[^ab]t'
→ c + 不是 a 或 b 的字符 + t
⚠️ 注意:如果
^
放在中间,就不取反,只是普通字符。
[yuxb@controller lab 15:25:40]$ cat words | grep 'c[a^b]t' cat category acat concatenate cbt
元字符匹配
.
任意字符
.
匹配除换行符外的 任意单个字符。
[yuxb@controller lab 15:25:52]$ cat words | grep 'c.t' cat category acat concatenate cbt c1t cCt c-t
解释:
-
'c.t'
→ c + 任意一个字符 + t -
所以 c 后面跟任意字符再跟 t 都能匹配。
转义符 \
让元字符变成普通字符,或者匹配特殊序列。
[yuxb@controller lab 15:26:50]$ echo c.t >> words [yuxb@controller lab 15:26:50]$ cat words | grep 'c\.t' c.t
解释:
-
.
→ 任意字符 -
\.
→ 真正的小数点 -
⚠️ 小白注意:转义符可以让符号按“原义”匹配。
或 |
(必须用 egrep
或 grep -E
)
匹配多个模式之一。
[yuxb@controller lab 15:27:02]$ cat words | egrep 'cat|dog' cat category acat concatenate dog
解释:
-
cat|dog
→ cat 或 dog -
|
相当于“或者”
定位符
符号 | 含义 | 举例 |
---|---|---|
^ | 行首 | grep '^cat' → 行开头是 cat |
$ | 行尾 | grep 'cat$' → 行结尾是 cat |
\b | 单词边界 | grep '\bcat\b' → 精确匹配独立的 cat |
\B | 非单词边界 | grep '\Bcat' → 匹配不是独立单词的 cat |
\< | 单词左边界 | grep '\<cat' |
\> | 单词右边界 | grep 'cat\>' |
示例:
[yuxb@controller lab 15:28:52]$ echo hello cat >> words [yuxb@controller lab 15:29:23]$ cat words | grep '\bcat\b' cat hello cat
解释:
-
\bcat\b
→ 找到独立的单词 cat -
不会匹配 category,因为 category 不是独立单词。
重复次数限定
* 0次或多次
[yuxb@controller lab 16:05:29]$ cat words | grep 'do*g' dog dg doog
解释:
-
'do*g'
→ d + 任意数量的 o(包括0个) + g
+ 1次或多次
[yuxb@controller lab 16:05:32]$ cat words | egrep 'do+g' dog doog
-
至少有一次 o 才能匹配。
?
0次或1次
[yuxb@controller lab 16:05:46]$ cat words | egrep 'do?g' dog dg
-
o 出现 0 次或 1 次。
{n}
精确匹配 n 次
[yuxb@controller lab 16:06:30]$ cat words | egrep 'do{2}g' doog
-
o 必须出现 2 次。
{m,n}
匹配 m~n 次
[yuxb@controller lab 16:06:43]$ cat words | egrep 'do{2,3}g' doog dooog
-
o 出现 2 到 3 次。
{m,}
匹配至少 m 次
[yuxb@controller lab 16:06:50]$ cat words | egrep 'do{2,}g' doog dooog doooog
-
o 至少出现 2 次。
{,n}
匹配至多 n 次
[yuxb@controller lab 16:07:05]$ cat words | egrep 'do{,3}g' dog dg doog dooog
-
o 出现 0~3 次。
()
标记子表达式
[yuxb@controller lab 16:07:42]$ echo dogdog >> words [yuxb@controller lab 16:07:42]$ echo dogdogdog >> words [yuxb@controller lab 16:07:42]$ echo dogdogdogdog >> words [yuxb@controller lab 16:07:42]$ cat words | egrep '(dog){2,3}' dogdog dogdogdog
解释:
-
(dog){2,3}
→ 匹配 2 到 3 个连续的 dog -
记法:先看小括号里面的内容,再看
{}
决定重复次数。
grep 命令实践
grep 命令语法
[yuxb@controller ~ 18:58:23]$ grep --help 用法: grep [选项]... PATTERN [FILE]... 在每个 FILE 或是标准输入中查找 PATTERN。 默认的 PATTERN 是一个基本正则表达式(BRE)。 例如: grep -i 'hello world' menu.h main.c
PATTERN → 你要查找的文本模式 FILE → 待查找的文件,如果不写,默认从标准输入读取(可以用管道
|
)
正则表达式类型
选项 | 含义 |
---|---|
-G | 基本正则表达式 (BRE) |
-E | 扩展正则表达式 (ERE),支持 `+ ? |
-F | 固定字符串匹配,不解析正则 |
-P | Perl 正则表达式,语法更丰富 |
匹配模式来源
选项 | 含义 |
---|---|
-e PATTERN | 直接指定模式 |
-f FILE | 从文件中读取模式,每行一个 |
忽略大小写 / 完整匹配
选项 | 含义 |
---|---|
-i | 忽略大小写 |
-w | 匹配完整单词 |
-x | 整行完全匹配 |
输出控制
选项 | 含义 |
---|---|
-v | 反转匹配,显示不匹配的行 |
-m NUM | 最多匹配 NUM 行 |
-c | 只显示匹配行数 |
-b | 显示字节偏移量 |
-n | 显示行号 |
-o | 只输出匹配的文本 |
-q | 静默模式,不输出内容,只返回退出状态 |
-s | 抑制错误信息 |
grep 命令选项实例
模式选择和解释选项
-E
或 egrep
-
作用:支持扩展正则表达式,能用
+ ? | {}
等高级语法 -
示例:
[yuxb@controller lab 19:08:06]$ cat words | grep -E '(dog){3}' dogdogdog dogdogdogdog # 或者等价写法 [yuxb@controller lab 19:08:08]$ cat words | egrep '(dog){3}' dogdogdog dogdogdogdog
提示:
(dog){3}
→ 连续匹配 3 次 dog
-e
-
作用:直接指定匹配模式,可多个
-e
-
示例:
[yuxb@controller lab 19:08:59]$ cat words | grep -e 'cat' -e 'dog' cat category acat concatenate dog hello cat dogdog dogdogdog dogdogdogdog
等价写法:
[yuxb@controller lab 19:09:00]$ cat words | egrep 'cat|dog' cat category acat concatenate dog hello cat dogdog dogdogdog dogdogdogdog
-f
-
作用:从文件读取模式,每行一个
-
示例:
[yuxb@controller lab 19:09:39]$ echo -e 'cat\ndog' > pattens_file [yuxb@controller lab 19:09:40]$ cat pattens_file cat dog [yuxb@controller lab 19:09:47]$ cat words | grep -f pattens_file cat category acat concatenate dog hello cat dogdog dogdogdog dogdogdogdog
提示:模式文件就像你手写的“查找清单”,每行一条要查的文本。
-i
忽略大小写
[yuxb@controller lab 19:09:47]$ cat words | grep -i 'cBt' cbt
忽略大小写后,
CBt
、cBt
、cbt
都能匹配。
-w
完整单词匹配
[yuxb@controller lab 19:11:36]$ cat words | grep -w 'cat' cat hello cat
不会匹配
category
,因为cat
不是独立单词 ⚠️ 等价写法:grep '\bcat\b'
-x
整行匹配
[yuxb@controller lab 19:12:11]$ cat words | grep -x 'cat' cat # 等价写法 [yuxb@controller lab 19:12:13]$ cat words | grep '^cat$' cat
只有整行完全和模式相同才匹配。
输出控制选项
-v
反转匹配
[yuxb@controller lab 19:15:45]$ cat words | egrep -v '^d|^c' acat hello cat
输出 不以 d 或 c 开头的行 ⚠️ 常用于过滤注释或空行:
[yuxb@controller lab 19:16:08]$ egrep -v '^ *#|^$' /etc/profile # 只显示真正配置内容,去掉注释和空行
-m NUM
匹配次数限制
[yuxb@controller lab 19:17:01]$ cat words | grep -m2 'dog' dog dogdog
匹配到前 2 个就停止搜索,加快速度。
-c
显示行数
[yuxb@controller lab 19:17:21]$ cat words | grep -c 'dog' 4
只显示匹配行的数量,不显示内容。
-b
显示字节偏移
[yuxb@controller lab 19:17:42]$ cat words | grep -b 'cat' 0:cat 4:category 13:acat 18:concatenate 54:hello cat
左边数字是 匹配行第一个字符在文件中的字节位置,方便定位。
-n
显示行号
[yuxb@controller lab 19:17:43]$ cat words | grep -n 'cat' 1:cat 2:category 3:acat 4:concatenate 11:hello cat
左边数字是 行号,方便查找。
-o
只输出匹配内容
[yuxb@controller lab 19:18:36]$ cat words | egrep -o '(dog){3}' dogdogdog dogdogdog
每个匹配结果单独一行。
-q
静默模式
[yuxb@controller lab 19:21:16]$ cat words | egrep -q '(dog){3}' [yuxb@controller lab 19:21:17]$ echo $? 0 [yuxb@controller lab 19:21:17]$ cat words | egrep -q '(dog){3}asdfasfdasf' [yuxb@controller lab 19:21:17]$ echo $? 1
找到匹配返回
0
,没找到返回1
,不输出任何内容,适合脚本判断。
-s
抑制错误
[yuxb@controller lab 19:21:56]$ grep '^SELINUX=' /etc/shadow /etc/selinux/config grep: /etc/shadow: 权限不够 /etc/selinux/config:SELINUX=disabled [yuxb@controller lab 19:21:57]$ grep -s '^SELINUX=' /etc/shadow /etc/selinux/config /etc/selinux/config:SELINUX=disabled
不想看到权限不足或文件不存在的报错,可以加
-s
。
set
sed 行寻址
sed
是一个流编辑器,支持通过 行号、范围、模式匹配 来选择要处理的行,这就是所谓的 行寻址。
sed 命令语法
基本格式
sed [选项] '地址 指令' 文件
-
地址:行寻址,用来指定作用的行(可以是行号、范围、正则匹配)
-
指令:
sed
的操作命令(如p
、d
、s
) -
文件:要处理的文本文件,如果省略则默认从标准输入读取
sed 帮助
[yuxb@controller web 09:37:42]$ sed --help 用法: sed [选项]... {脚本(如果没有其他脚本)} [输入文件]... -n, --quiet, --silent 取消自动打印模式空间 -e 脚本, --expression=脚本 添加“脚本”到程序的运行列表 -f 脚本文件, --file=脚本文件 添加“脚本文件”到程序的运行列表 --follow-symlinks 直接修改文件时跟随软链接 -i[SUFFIX], --in-place[=SUFFIX] edit files in place (makes backup if SUFFIX supplied) -c, --copy use copy instead of rename when shuffling files in -i mode -b, --binary does nothing; for compatibility with WIN32/CYGWIN/MSDOS/EMX ( open files in binary mode (CR+LFs are not treated specially)) -l N, --line-length=N 指定“l”命令的换行期望长度 --posix 关闭所有 GNU 扩展 -r, --regexp-extended 在脚本中使用扩展正则表达式 -s, --separate 将输入文件视为各个独立的文件而不是一个长的连续输入 -u, --unbuffered 从输入文件读取最少的数据,更频繁的刷新输出 -z, --null-data separate lines by NUL characters --help display this help and exit --version output version information and exit 如果没有 -e, --expression, -f 或 --file 选项,那么第一个非选项参数被视为 sed脚本。其他非选项参数被视为输入文件,如果没有输入文件,那么程序将从标准 输入读取数据。 GNU sed home page: <http://www.gnu.org/software/sed/>. General help using GNU software: <http://www.gnu.org/gethelp/>. E-mail bug reports to: <bug-sed@gnu.org>. Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
示例1:模拟cat命令打印文件内容
[yuxb@controller lab 10:21:38]$ cat data.txt I am studing sed I am www.twle.cn I am a no-work-men I am so handsome [yuxb@controller lab 10:22:07]$ sed '' data.txt I am studing sed I am www.twle.cn I am a no-work-men I am so handsome
示例2:从标准输入中读取数据
[yuxb@controller lab 10:22:12]$ sed '' # 输入hello world,并回车 hello world # 输出hello world hello world # 按ctrl+d退出
常用选项
选项 | 说明 |
---|---|
-n | 安静模式(默认 sed 会输出所有行,加 -n 后只输出匹配或指定操作的结果) |
-e | 多重编辑,允许指定多个编辑命令 |
-f | 从脚本文件读取 sed 命令 |
-i | 直接修改原文件(慎用,会覆盖原文件) |
-e —— 多重编辑(expression)
-
允许在一条命令中指定多个编辑操作。
-
不加
-e
也能用,但多个命令必须分开写;有了-e
更清晰。
# 打印data.txt文件内容 [yuxb@controller lab 10:23:33]$ sed -e '' data.txt I am studing sed I am www.twle.cn I am a no-work-men I am so handsome # 如果只有一个命令,-e选项可以省略 [yuxb@controller lab 10:24:07]$ sed '' data.txt I am studing sed I am www.twle.cn I am a no-work-men I am so handsome # -e 选项可以多次使用,1d是作用是删除第一行 # 没有第五行,就没有删除效果 [yuxb@controller lab 10:24:08]$ sed -e '1d' -e '2d' -e '5d' data.txt I am a no-work-men I am so handsome # 使用分号(;)分开多个命令 [yuxb@controller lab 10:24:27]$ sed -e '1d;2d;5d' data.txt I am a no-work-men I am so handsome
-f—— 从脚本文件读取命令(file)
-
把
sed
命令写在脚本文件里,方便复用。
[yuxb@controller lab 10:25:34]$ echo -e "1d\n2d\n5d" > scripts [yuxb@controller lab 10:25:35]$ cat scripts 1d 2d 5d [yuxb@controller lab 10:25:40]$ sed -f scripts data.txt I am a no-work-men I am so handsome
-n——安静模式(silent)
-
默认情况下,
sed
会把 所有行 输出到标准输出。
-
加上
-n
之后,只会输出符合条件的内容。
-
通常和
p
(print)命令一起用。
# 没有输出 [yuxb@controller lab 10:26:12]$ sed -n '' data.txt # 打印第一行记录 [yuxb@controller lab 10:26:13]$ sed -n '1p' data.txt I am studing sed
总结对比
选项 | 全称 | 作用 | 常见用途 |
---|---|---|---|
-n | --quiet / --silent | 关闭默认输出,只显示需要的结果 | sed -n '1,3p' file |
-e | --expression | 指定多个命令(行内) | sed -e '2d' -e 's/x/y/' file |
-f | --file | 从外部文件读取命令 | sed -f cmds.sed file |
sed 行寻址
基本语法
sed '[地址] 命令' 文件
-
地址(line address):用来指定
sed
命令作用的行,可以是行号、范围、正则匹配等。 -
命令:如
p
、d
、s
等。
示例
[yuxb@controller lab 10:27:45]$ echo 'This is 1 > This is 2 > This is 3 > This is 4 > This is 5 ' > test
示例1: 打印所有行
[yuxb@controller lab 10:27:48]$ cat test | sed '' This is 1 This is 2 This is 3 This is 4 This is 5 [yuxb@controller lab 10:29:29]$ cat test | sed -n 'p' This is 1 This is 2 This is 3 This is 4 This is 5 # -n 关闭sed打印模式缓冲区中所有内容。 # p命令,明确打印输出模式缓冲区中所有内容。
示例2: 打印特定行
[yuxb@controller lab 10:29:53]$ cat test | sed -n '1p' This is 1 [yuxb@controller lab 10:30:40]$ cat test | sed -n '$p' This is 5
示例3: 打印第1行到3行
[yuxb@controller lab 10:30:47]$ cat test | sed -n '1,3p' This is 1 This is 2 This is 3
示例4: 打印第3行到最后一行
[yuxb@controller lab 10:32:18]$ cat test | sed -n '3,$p' This is 3 This is 4 This is 5
示例5: 连续输出,打印第2行以及后续两行
[yuxb@controller lab 10:32:40]$ cat test | sed -n '2,+2p' This is 2 This is 3 This is 4
示例6: 隔行输出,打印第1行以及后续隔2行输出
[yuxb@controller lab 10:32:55]$ cat test | sed -n '1~2p' This is 1 This is 3 This is 5
sed 模式寻址
基本语法
sed '/模式/ 命令' 文件
-
/模式/
:正则表达式,用来匹配行 -
命令
:对匹配到的行执行操作,如p
、d
、s
等
准备文件
[yuxb@controller lab 10:35:56]$ cat << 'EOF' > ~/test > root:x:0:0:root:/root:/bin/bash > bin:x:1:1:bin:/bin:/bin/false > daemon:x:2:2:daemon:/sbin:/bin/false > mail:x:8:12:mail:/var/spool/mail:/bin/false > ftp:x:14:11:ftp:/home/ftp:/bin/false > &nobody:$:99:99:nobody:/:/bin/false > zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash > http:x:33:33::/srv/http:/bin/false > dbus:x:81:81:System message bus:/:/bin/false > hal:x:82:82:HAL daemon:/:/bin/false > mysql:x:89:89::/var/lib/mysql:/bin/false > aaa:x:1001:1001::/home/aaa:/bin/bash > ba:x:1002:1002::/home/zhangy:/bin/bash > test:x:1003:1003::/home/test:/bin/bash > @zhangying:*:1004:1004::/home/test:/bin/bash > policykit:x:102:1005:Po > EOF
示例1: 打印含有字符串zhang的行
[yuxb@controller ~ 10:36:36]$ cat test | sed -n '/zhang/p' zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash # -n # 作用:关闭 sed 的默认输出。 # 默认情况下,sed 会把每一行都输出一次,加 -n 后 只输出显式指定打印的行。 # /zhang/ # 作用:模式匹配,匹配所有 包含 zhang 的行。 # /模式/ 的形式就是 模式寻址。 # p # 作用:打印匹配到的行。 # 因为我们加了 -n,所以只有匹配的行会被打印出来。
示例2: 打印root开头的行到zhang开头的行
[yuxb@controller ~ 10:36:41]$ cat test | sed -n '/^root/,/^mail/p' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false # /^mail/ # 作用:匹配 以 mail 开头的行。 # 这是 结束行模式。
示例3: 打印root开头的行到第三行
[yuxb@controller ~ 10:36:54]$ cat test | sed -n '/^root/,3p' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false # /^root/ # 作用:匹配所有 以 root 开头的行。 # ^ 表示行首。 # 这是 模式寻址 的起始位置。 # ,3 # 作用:范围结束在 第 3 行。 # 表示从匹配到 /^root/ 的行开始,到 第 3 行 结束。
示例4: 打印root开头的行到最后一行
[yuxb@controller ~ 10:37:08]$ cat test | sed -n '/^root/,$p' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash test:x:1003:1003::/home/test:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po # ,$ # 作用:指定范围的结束行为 最后一行。 # $ 是 sed 中的特殊符号,表示 文件的最后一行。
sed 子命令
打印
作用
-
p,打印模式空间所有记录。
-
P,打印模式空间第一行记录。
语法
sed -n '地址p' 文件 sed -n '地址P' 文件
地址
:行寻址(可以是行号、范围、模式),用于指定要打印的行。
p
:打印匹配的整行。
P
:打印匹配的第一行内容(遇到换行符就停)。
示例
[yuxb@controller ~ 10:37:28]$ echo 'This is 1 > This is 2 > This is 3' | sed -n '1{N;p}' This is 1 This is 2 # 1{...} → 只对第 1 行执行大括号里的命令。 # N → 把 下一行(第 2 行)也读进模式空间,此时模式空间包含: # This is 1\nThis is 2 # p → 打印整个模式空间。 [yuxb@controller ~ 10:38:58]$ echo 'This is 1 > This is 2 > This is 3' | sed -n '1{N;P}' This is 1 # N → 把第 1 行和第 2 行一起放到模式空间:This is 1\nThis is 2 # P → 只打印 模式空间的第一行(直到第一个换行符为止)。 # 可以记成: # p = print all # P = print first
读取下一行
[yuxb@controller ~ 10:39:00]$ echo 'This is 1 > This is 2 > This is 3 > This is 4 > This is 5' | sed -n 'n;p' This is 2 This is 4 # n # 读入下一行到模式空间,并覆盖当前内容。 # 默认会打印当前模式空间的内容(但因为用了 -n,默认输出被抑制了)。 # p # 打印模式空间的内容。 # 逐步执行: # 读入第 1 行 "This is 1" → 模式空间 # 执行 n → 丢弃第 1 行,读入第 2 行 "This is 2" # 执行 p → 打印 "This is 2" # 读入第 3 行 "This is 3" → 模式空间 # 执行 n → 丢弃第 3 行,读入第 4 行 "This is 4" # 执行 p → 打印 "This is 4" # 读入第 5 行 "This is 5" → 模式空间 # 执行 n → 试图读下一行,但没有了 → 结束,不打印 # sed -n 'n;p' 的逻辑是: # 丢掉奇数行,只打印偶数行。
示例1: 成对合并行
[yuxb@controller ~ 10:43:35]$ cat test | sed 'N;s/\n/==/' root:x:0:0:root:/root:/bin/bash==bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false==mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false==&nobody:$:99:99:nobody:/:/bin/false zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash==http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false==hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false==aaa:x:1001:1001::/home/aaa:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash==test:x:1003:1003::/home/test:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash==policykit:x:102:1005:Po # N:把下一行读入模式空间,并在当前行后面加上一个换行符 \n。 # s/\n/==/:把换行符替换成 ==。
示例2: 打印前2行
[yuxb@controller ~ 10:44:15]$ echo 'This is 1 > This is 2 > This is 3 > This is 4 > This is 5' | sed -n '1{N;p}' This is 1 This is 2
替换
示例1:把test文件中的root替换成tankzhang,只不过只替换一次即终止在这一行的操作,并转到下一行
[yuxb@controller ~ 10:45:06]$ sed 's/root/tankzhang/' test|grep tankzhang tankzhang:x:0:0:root:/root:/bin/bash # s:substitute(替换) # root:匹配的模式 # tankzhang:替换后的字符串 # 没有加 g 标志 → 默认只替换 当前行的第一个匹配
示例2:把test文件中的root全部替换成tankzhang。字母g是global的缩写。
[yuxb@controller ~ 10:45:07]$ sed 's/root/tankzhang/g' test |grep tankzhang tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例3:加了-n
和p
后表示只打印那些发生替换的行(部分替换),下面的例子,不需要使用grep命令
[yuxb@controller ~ 10:45:23]$ sed -n 's/root/tankzhang/p' test tankzhang:x:0:0:root:/root:/bin/bash # -n:禁止默认输出(静默模式)。 # s/root/tankzhang/:替换命令,把 root 替换为 tankzhang(每行只替换第一个)。 # p:打印发生替换的行。
示例4:加了-n
和pg
后表示只打印那些发生替换的行(全部替换)
[yuxb@controller ~ 10:47:10]$ sed -n 's/root/tankzhang/gp' test tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例5:在第二行到第八行之间,替换以zhang开头的行,用ying来替换,并显示替换的行
[yuxb@controller ~ 10:47:31]$ sed -ne '2,8s/^zhang/ying/gp' test yingy:x:1000:100:,,,:/home/zhangy:/bin/bash # -n:静默模式,不输出未被指定的行。 # 2,8:只对 第 2 行到第 8 行 之间的内容生效。 # s/^zhang/ying/g:把行首的 zhang 替换为 ying。 # ^zhang 表示以 zhang 开头。 # g 表示全局替换(虽然这里一行只有一个匹配点)。 # p:只打印替换成功的行。
示例6: 从以zhang开头的行开始,到匹配Po的行结束,在他们之间进行替换
[yuxb@controller ~ 10:47:32]$ sed -ne '/^zhang/,/Po/ s/zhang/ying/gp' test yingy:x:1000:100:,,,:/home/yingy:/bin/bash ba:x:1002:1002::/home/yingy:/bin/bash @yingying:*:1004:1004::/home/test:/bin/bash # -n # 不自动打印,避免多余输出,只显示你显式指定的结果。 # -e 'script' # 明确告诉 sed 执行的脚本(这里只有一个,可以省略 -e)。 # /^zhang/,/Po/ # 这是一个 区间寻址,起点是匹配 ^zhang 的行(以 zhang 开头的行), # 终点是匹配 Po 的行(包含 Po 的行)。 # 这两者之间的所有行(包括起止行),都会执行后面跟的命令。 # s/zhang/ying/gp # s/zhang/ying/ → 替换第一个匹配的 zhang 为 ying。 # g → 全局替换该行中所有 zhang。 # p → 打印发生替换的行。
替换中的分隔符可以自定义,默认是/。
示例7: 自定义替换分隔符为 #
。
sed
允许你自定义分隔符,比如 #
、@
、|
等。
[yuxb@controller ~ 10:47:49]$ sed -n 's#root#hello#gp' test hello:x:0:0:hello:/hello:/bin/bash
分隔符;和-e选项
需要执行多个sed处理命令时,用分号分开,或者使用 -e
选项。
示例:
-
在第2行到第8行之间,替换以zhang开头的行,用ying来替换
-
在第5行到第10行之间,用goodbay来替换dbus,并显示替换的行
[yuxb@controller ~ 10:48:57]$ cat test | sed -n [yuxb@controller ~ 10:48:39]$ cat test | sed -ne '2,8s/zhang/ying/gp' -ne '5,10s#dbus#goodbay#gp' yingy:x:1000:100:,,,:/home/yingy:/bin/bash goodbay:x:81:81:System message bus:/:/bin/false
使用场景对比
写法 | 特点 | 适用场景 |
---|---|---|
; 分隔命令 | 简洁,但命令太多时可读性差 | 短小的一次性脚本 |
-e 多条命令 | 清晰,适合复杂脚本或多命令 | 推荐长期使用 |
插入
命令 | 作用 |
---|---|
a | 在匹配行 后 插入 |
i | 在匹配行 前 插入 |
c | 整行替换 |
a 在匹配行下面插入新行
将要插入的东西,插入到匹配行的下面
[yuxb@controller ~ 10:49:09]$ sed '/root/a====aaaa====' test root:x:0:0:root:/root:/bin/bash ====aaaa==== bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash test:x:1003:1003::/home/test:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po
i 在匹配行上面插入新行
将要插入的东西,插入到匹配行的上面
[yuxb@controller ~ 10:50:19]$ sed '/root/i====iiii====' test ====iiii==== root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash test:x:1003:1003::/home/test:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po
删除
作用
-
d,删除模式空间所有记录。
-
D,删除模式空间第一行记录。
语法
sed '地址范围d' 文件 sed '地址范围D' 文件
d 删除 示例
示例1: 删除1,14行
[yuxb@controller ~ 10:51:19]$ sed -e '1,14d' test @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po
示例2: 删除4以后的行,包括第4行,把$当成最大行数就行了。
[yuxb@controller ~ 10:51:20]$ sed -e '4,$d' test root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false
示例3: 删除包括false的行,或者包括bash的行,别忘了加\
[yuxb@controller ~ 10:52:33]$ sed -e '/\(false\|bash\)/d' test policykit:x:102:1005:Po
示例4: 删除从匹配root的行,到匹配以test开头的行,中间的行
[yuxb@controller ~ 10:52:33]$ sed -e '/root/,/^test/d' test @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po
D 删除 示例
删除当前模式空间开端至\n的内容,放弃之后的命令,对剩余模式空间继续执行sed。
示例1:读取最后一行内容
[yuxb@controller ~ 10:53:47]$ echo 'This is 1 > This is 2 > This is 3 > This is 4 > This is 5' | sed 'N;D' This is 5
示例2:删除偶数行
[yuxb@controller ~ 10:53:49]$ echo 'This is 1 > This is 2 > This is 3 > This is 4 > This is 5' | sed 'n;D' This is 1 This is 3 This is 5
打印行号
=
打印当前处理的 行号。
语法
sed '=' 文件名
示例1:行号与行内容交替显示
[yuxb@controller ~ 10:54:10]$ sed '=' test 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/bin/false 3 daemon:x:2:2:daemon:/sbin:/bin/false 4 mail:x:8:12:mail:/var/spool/mail:/bin/false 5 ftp:x:14:11:ftp:/home/ftp:/bin/false 6 &nobody:$:99:99:nobody:/:/bin/false 7 zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash 8 http:x:33:33::/srv/http:/bin/false 9 dbus:x:81:81:System message bus:/:/bin/false 10 hal:x:82:82:HAL daemon:/:/bin/false 11 mysql:x:89:89::/var/lib/mysql:/bin/false 12 aaa:x:1001:1001::/home/aaa:/bin/bash 13 ba:x:1002:1002::/home/zhangy:/bin/bash 14 test:x:1003:1003::/home/test:/bin/bash 15 @zhangying:*:1004:1004::/home/test:/bin/bash 16 policykit:x:102:1005:Po
示例2:行号与行内容并排显示
# 利用 sed 'N;s/\n/:/' 把行号和内容合并到同一行 [yuxb@controller ~ 10:54:52]$ sed '=' test| sed 'N;s/\n/:/' 1:root:x:0:0:root:/root:/bin/bash 2:bin:x:1:1:bin:/bin:/bin/false 3:daemon:x:2:2:daemon:/sbin:/bin/false 4:mail:x:8:12:mail:/var/spool/mail:/bin/false 5:ftp:x:14:11:ftp:/home/ftp:/bin/false 6:&nobody:$:99:99:nobody:/:/bin/false 7:zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash 8:http:x:33:33::/srv/http:/bin/false 9:dbus:x:81:81:System message bus:/:/bin/false 10:hal:x:82:82:HAL daemon:/:/bin/false 11:mysql:x:89:89::/var/lib/mysql:/bin/false 12:aaa:x:1001:1001::/home/aaa:/bin/bash 13:ba:x:1002:1002::/home/zhangy:/bin/bash 14:test:x:1003:1003::/home/test:/bin/bash 15:@zhangying:*:1004:1004::/home/test:/bin/bash 16:policykit:x:102:1005:Po
写入
w 写入
将模式空间中记录写入到文件中。
示例1: 将root开头的行,写入test3中
[yuxb@controller ~ 10:55:51]$ sed -n '/^root/w test3' test [yuxb@controller ~ 10:55:51]$ cat test3 root:x:0:0:root:/root:/bin/bash # -n # 表示 不自动打印模式空间的内容,避免把所有行都输出到终端。 # /^root/ # 表示 匹配以 root 开头的行。 # w test3 # 把模式空间中 匹配到的行写入文件 test3。
W 写入
将模式空间中第一条记录写入到文件中。
示例: 写入记录
[yuxb@controller ~ 10:55:56]$ vim scripts [yuxb@controller ~ 10:56:38]$ cat scripts 1{ N w write.log # w write.log → 把整个模式空间写入 write.log } # 小写w写入包含模式中所有行 [yuxb@controller ~ 10:57:04]$ cat write.log root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/false # 大写W写入只包含模式中第一行 [yuxb@controller ~ 10:57:05]$ vim scripts [yuxb@controller ~ 10:58:01]$ cat scripts 1{ N W write.log } [yuxb@controller ~ 10:58:11]$ sed -n -f scripts test [yuxb@controller ~ 10:58:20]$ cat write.log root:x:0:0:root:/root:/bin/bash
更改
整行替换。
作用
-
用新的内容替换匹配的整行。
-
在
sed
中有两种常用方式:
示例:root开头行替换出hello
# chello → 将匹配行整行替换为 hello [yuxb@controller ~ 10:58:49]$ sed '/^root/chello' test hello bin:x:1:1:bin:/bin:/bin/false daemon:x:2:2:daemon:/sbin:/bin/false mail:x:8:12:mail:/var/spool/mail:/bin/false ftp:x:14:11:ftp:/home/ftp:/bin/false &nobody:$:99:99:nobody:/:/bin/false zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash http:x:33:33::/srv/http:/bin/false dbus:x:81:81:System message bus:/:/bin/false hal:x:82:82:HAL daemon:/:/bin/false mysql:x:89:89::/var/lib/mysql:/bin/false aaa:x:1001:1001::/home/aaa:/bin/bash ba:x:1002:1002::/home/zhangy:/bin/bash test:x:1003:1003::/home/test:/bin/bash @zhangying:*:1004:1004::/home/test:/bin/bash policykit:x:102:1005:Po # 等效下面命令 [yuxb@controller ~ 10:58:49]$ sed 's/^root.*/hello/' test
awk
awk
是一个功能强大的文本处理工具,主要用于按 字段 和 模式 对文本进行扫描、分析和处理。
awk 命令
基本语法
awk '模式 {动作}' 文件
-
模式(pattern):用来匹配行,可以是正则表达式,也可以是逻辑判断。
-
动作(action):对匹配行执行的操作,用
{}
包裹。
如果省略模式,则作用于所有行。 如果省略动作,默认打印匹配行。
常用选项
选项 | 作用 |
---|---|
-F 分隔符 | 指定输入字段分隔符,默认空格或制表符 |
-v var=value | 定义 awk 变量 |
-f 脚本文件 | 从文件中读取 awk 脚本 |
awk 示例
示例文件
[yuxb@controller ~ 11:22:24]$ cat << 'EOF' > employee.txt > 1) 张三 技术部 23 > 2) 李四 人力部 22 > 3) 王五 行政部 23 > 4) 赵六 技术部 24 > 5) 朱七 客服部 23 > EOF
示例1: 打印雇员信息。
# { print } → 打印模式空间的整行内容(等同于 print $0)。 [yuxb@controller ~ 11:22:52]$ awk '{ print }' employee.txt 1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
示例2: 通过读取awk脚本,打印雇员信息。
[yuxb@controller ~ 11:25:31]$ cat commands.awk { print } # -f commands.awk → 指定 awk 脚本文件执行。 [yuxb@controller ~ 11:25:34]$ awk -f commands.awk employee.txt 1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23
示例3: 输出特定隔行。
# /pattern/ 是 awk 最常用的 模式匹配方式 [yuxb@controller ~ 11:25:43]$ awk '/张三/ { print }' employee.txt 1) 张三 技术部 23 [yuxb@controller ~ 11:25:59]$ awk '/张三/' employee.txt 1) 张三 技术部 23
示例4: 统计满足特定条件的记录数。
[yuxb@controller ~ 11:26:05]$ awk ' > /术/ { count=count+1 } > END { print "Count="count }' employee.txt Count=2 # /术/ → 匹配包含“术”的行(如“技术部”)。 # { count = count + 1 } → 每匹配一行,计数器 count 加 1。 # END { print "Count=" count } → 在处理完所有行后打印结果。
示例5: 输出总长度大于 10 的行。
[yuxb@controller ~ 11:26:38]$ awk 'length($0)>10 { print $0 }' employee.txt 1) 张三 技术部 23 2) 李四 人力部 22 3) 王五 行政部 23 4) 赵六 技术部 24 5) 朱七 客服部 23 # length($0) → 获取当前行的长度(字符数)。 # length($0) > 10 → 条件判断,总长度大于 10 的行才执行 { print $0 }。 # $0 → 当前整行内容。
Shell 变量
Shell 变量用于在脚本中存储数据,可以是数字、字符串或命令输出。
Shell 中特殊变量
位置参数
变量 | 说明 |
---|---|
$0 | 脚本名称 |
$1 ~$9 | 第1~第9个参数 |
$# | 参数个数 |
$@ | 所有参数,逐个引用 |
$* | 所有参数,作为一个整体 |
$$ | 当前脚本的 PID |
$! | 上一个后台运行命令的 PID |
$? | 上一个命令的退出状态(0 成功,非0失败) |
Shell 位置参数变量
示例1:showargs.sh 内容如下
#!/bin/bash echo $0 echo $1 echo $2 echo $10 echo ${10} echo $# echo $* echo $@ echo "$@"
[yuxb@controller bin 15:01:59]$ bash showargs.sh {a..z} showargs.sh a b a0 j 26 a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z
示例2:ssh_ctl 内容如下
#!/bin/bash systemctl $1 sshd
[yuxb@controller bin 15:04:32]$ sudo ~/bin/ssh_ctl stop [yuxb@controller bin 15:05:53]$ sudo ~/bin/ssh_ctl status [yuxb@controller bin 15:05:59]$ sudo ~/bin/ssh_ctl start
Shell 进程中的特殊状态变量
$?
作用:获取执行上一个指令的执行状态返回值:0为成功,非0为失败,这个变量最常用。
只能获取 上一个命令 的状态,执行新命令后会被覆盖。
在脚本中,可以用它实现 错误处理和异常退出。
[yuxb@controller bin 14:57:08]$ echo $? 1 [yuxb@controller bin 14:57:20]$ ls /root ls: 无法打开目录/root: 权限不够 [yuxb@controller bin 14:57:32]$ echo $? 2 [yuxb@controller bin 14:57:34]$
$$
作用:获取当前执行的 Shell 脚本的进程号(PID),这个变量不常用,了解即可。
[yuxb@controller bin 14:58:30]$ echo $$ 1553
$!
作用:获取上一个在后台工作的进程的进程号(PID),这个变量不常用,了解即可。
[yuxb@controller bin 14:59:11]$ md5sum /dev/zero & [1] 2696 [yuxb@controller bin 14:59:14]$ echo $! 2696 [yuxb@controller bin 14:59:23]$ ps o pid,%cpu,%mem,command $! PID %CPU %MEM COMMAND 2696 100 0.0 md5sum /dev/zero [yuxb@controller bin 14:59:29]$ kill $! [1]+ 已终止 md5sum /dev/zero
$_
作用:获取在此之前执行的命令或脚本的最后一个参数,这个变量不常用,了解即可。
[yuxb@controller bin 14:59:36]$ ls /etc/hosts /etc/fstab /etc/hostname /etc/fstab /etc/hostname /etc/hosts [yuxb@controller bin 15:00:03]$ cat $_ controller.yuxb.cloud [yuxb@controller bin 15:00:07]$ cat /etc/hostname controller.yuxb.cloud
Shell 内置变量命令
echo
echo命令参数选项:
-
-n,不换行输出内容。
-
-e,解析转义字符(见下面的字符)
转义字符:
-
\n,换行。
-
\t,制表符(tab)。
-
\b,退格。
[yuxb@controller bin 15:06:03]$ echo -n "laowang";echo laoli laowanglaoli [yuxb@controller bin 15:07:24]$ echo -e "laowang\nlaoli" laowang laoli [yuxb@controller bin 15:08:21]$ echo -e "laowang\tlaoli" laowang laoli [yuxb@controller bin 15:08:42]$ echo -e "1\b23" 23 [yuxb@controller bin 15:09:04]$ echo -e "123\b" 123 [yuxb@controller bin 15:09:08]$ echo -ne "123\b";echo haha 12haha
read
[yuxb@controller bin 15:16:59]$ vim read.sh [yuxb@controller bin 15:17:13]$ cat read.sh #!/bin/sh read -p "输入你想要说的话:" str echo "你想要说的话是:$str" [yuxb@controller bin 15:17:25]$ bash read.sh 输入你想要说的话:666 你想要说的话是:666 [yuxb@controller bin 15:17:29]$ read -s -p "请设置用户密码: " password 请设置用户密码: [yuxb@controller bin 15:17:48]$ echo $password 123
Shell 变量子串知识
Shell 变量子串介绍
在 Shell 脚本中,可以对变量内容进行 截取、替换、删除等操作,方便处理字符串数据。
取子串(Substring)
${变量名:起始位置:长度}
-
起始位置从
0
开始计数 -
长度可选,如果省略则取到字符串末尾
Shell 变量子串的实践
示例1: ${parameter}
[yuxb@controller bin 15:20:43]$ str="abc123abc123" [yuxb@controller bin 15:29:52]$ echo ${str} abc123abc123
示例2:${#parameter}
# 获得字符串长度 [yuxb@controller bin 15:29:57]$ str="abc123abc123" [yuxb@controller bin 15:30:11]$ echo ${#str} 12 # 其他方法 [yuxb@controller bin 15:30:46]$ echo ${str} | wc -L # wc -L 输出最长行的字符数 12 [yuxb@controller bin 15:30:47]$ expr length "${str}" # expr 是外部命令 12 [yuxb@controller bin 15:30:51]$ echo "$str" | awk '{ print length($0)}' # awk 的 length() 函数也能统计字符串长度 12
示例3:${parameter:offset}
和 ${parameter:offset:length}
# 提取子串 [yuxb@controller bin 15:30:57]$ str="abc123abc123" # 从下标 3 开始截取(从0开始计数) [yuxb@controller bin 15:31:26]$ echo ${str:3} 123abc123 # 从下标 3 开始,截取 4 个字符 [yuxb@controller bin 15:31:30]$ echo ${str:3:4} 123a
示例4:${parameter#word}
和 ${parameter##word}
[yuxb@controller bin 15:31:34]$ str="abc123abc123" # 从左侧开始删除子串 [yuxb@controller bin 15:31:57]$ echo ${str#b*a} abc123abc123 # 未匹配到,第一个字符必须与元字串第一个子符一致 [yuxb@controller bin 15:32:04]$ echo ${str#a*c} 123abc123 [yuxb@controller bin 15:32:17]$ echo ${str##a*c} 123 # # → 删除最短匹配前缀 # ## → 删除最长匹配前缀 # 类似操作也可以用于 后缀删除(% 和 %%)
示例5:${parameter%word}
和 ${parameter%%word}
[yuxb@controller bin 15:32:21]$ str="abc123abc123" # 从右侧开始删除子串 [yuxb@controller bin 15:33:12]$ echo ${str%a*c} abc123abc123 # 未匹配到,最后一个字符必须与元字串最后一个子符一致 [yuxb@controller bin 15:33:18]$ echo ${str%c*3} abc123ab [yuxb@controller bin 15:33:28]$ echo ${str%%c*3} ab # % → 删除最短匹配后缀 # %% → 删除最长匹配后缀 # 前缀删除(#、##)和后缀删除(%、%%)常用于 路径、文件名、字符串处理
示例6:${parameter/pattem/string}
[yuxb@controller bin 15:33:33]$ str="abc123abc123" # 只替换第一个 [yuxb@controller bin 15:34:05]$ echo ${str/abc/def} def123abc123 # 所有的全替换 [yuxb@controller bin 15:34:10]$ echo ${str//abc/def} def123def123 # ${变量/旧/新} → 只替换第一个 # ${变量//旧/新} → 全部替换
Shell 脚本的条件测试
文件判断表达式
Bash 条件判断和目录操作
[yuxb@controller bin 16:50:54]$ [ -r /etc/shadow ] && echo i can read /etc/shadow [yuxb@controller bin 16:51:25]$ ls -l /etc/shadow ---------- 1 root root 776 8月 19 14:31 /etc/shadow [yuxb@controller bin 16:51:37]$ [ ! -r /etc/shadow ] && echo i can not read /etc/shadow i can not read /etc/shadow [yuxb@controller bin 16:51:57]$ [ -d $path ] && echo $path is a directory is a directory [yuxb@controller bin 16:52:36]$ ls $path 666.sh 999.sh eval.sh monitory_os noeval.sh read.sh showargs.sh ssh_ctl [yuxb@controller bin 16:53:28]$ [ ! -d $path ] && echo $path is not a directory [yuxb@controller bin 16:53:38]$ [ ! -d $path ] && mkdir $path && echo 创建 $path 成功 Try 'rmdir --help' for more information. [yuxb@controller bin 16:56:22]$ ls $path 666.sh 999.sh eval.sh monitory_os noeval.sh read.sh showargs.sh ssh_ctl [yuxb@controller bin 16:56:58]$ [ -d $path ] && echo $path is exist is exist [yuxb@controller bin 16:57:57]$ path=/tmp/data [yuxb@controller bin 16:58:55]$ mkdir $path [yuxb@controller bin 16:58:56]$ [ -d $path ] && echo $path is exist /tmp/data is exist [yuxb@controller bin 17:00:14]$ [ -d $path ] || mkdir $path [yuxb@controller bin 17:00:46]$ ls $path
判断当前用户是否是root用户
[yuxb@controller bin 17:18:16]$ vim 123.sh [yuxb@controller bin 17:19:11]$ cat 123.sh #!/bin/bash [ "$(whoami)" != "root" ] && echo pls run as root. && exit [ "$USER" != "root" ] && echo pls run as root. && exit [ "$UID" -ne 0 ] && echo pls run as root. && exit ((UID!=0)) && echo pls run as root. && exit [yuxb@controller bin 17:19:51]$ chmod +x 123.sh [yuxb@controller bin 17:19:57]$ 123.sh pls run as root.