Linux 文本处理与 Shell 编程笔记:正则表达式、sed、awk 与变量脚本
Linux 正则表达式
环境示例
[yuxb@controller ~ 15:21:42]$ cat words catcategoryacatconcatenatedog
words
文件包含一些单词,用于测试正则表达式。
普通字符匹配
最简单的匹配方式:直接找文件里有 完全相同的文本。
[yuxb@controller lab 15:22:46]$ cat words | grep 'cat'catcategoryacatconcatenate
解释:
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'catcategoryacatconcatenatecbt
解释:
[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'catcategoryacatconcatenatecbt[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'catcategoryacatconcatenatecbtc1t
⚠️ 注意:字符集中的
-
如果要匹配普通字符,要放在最前面或最后面。
[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'catcategoryacatconcatenatecbtc1tcCtc-t
取反 [^...]
^
放在方括号开头 → 匹配 不在里面的字符。
[yuxb@controller lab 15:25:39]$ cat words | grep 'c[^ab]t'c1tcCtc-t
解释:
[^ab]
→ 不是 a 或 b 的任意字符'c[^ab]t'
→ c + 不是 a 或 b 的字符 + t
⚠️ 注意:如果
^
放在中间,就不取反,只是普通字符。
[yuxb@controller lab 15:25:40]$ cat words | grep 'c[a^b]t'catcategoryacatconcatenatecbt
元字符匹配
.
任意字符
.
匹配除换行符外的 任意单个字符。
[yuxb@controller lab 15:25:52]$ cat words | grep 'c.t'catcategoryacatconcatenatecbtc1tcCtc-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'catcategoryacatconcatenatedog
解释:
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'cathello cat
解释:
\bcat\b
→ 找到独立的单词 cat不会匹配 category,因为 category 不是独立单词。
重复次数限定
* 0次或多次
[yuxb@controller lab 16:05:29]$ cat words | grep 'do*g'dogdgdoog
解释:
'do*g'
→ d + 任意数量的 o(包括0个) + g
+ 1次或多次
[yuxb@controller lab 16:05:32]$ cat words | egrep 'do+g'dogdoog
至少有一次 o 才能匹配。
?
0次或1次
[yuxb@controller lab 16:05:46]$ cat words | egrep 'do?g'dogdg
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'doogdooog
o 出现 2 到 3 次。
{m,}
匹配至少 m 次
[yuxb@controller lab 16:06:50]$ cat words | egrep 'do{2,}g'doogdooogdoooog
o 至少出现 2 次。
{,n}
匹配至多 n 次
[yuxb@controller lab 16:07:05]$ cat words | egrep 'do{,3}g'dogdgdoogdooog
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}'dogdogdogdogdog
解释:
(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}'dogdogdogdogdogdogdog# 或者等价写法[yuxb@controller lab 19:08:08]$ cat words | egrep '(dog){3}'dogdogdogdogdogdogdog
提示:
(dog){3}
→ 连续匹配 3 次 dog
-e
作用:直接指定匹配模式,可多个
-e
示例:
[yuxb@controller lab 19:08:59]$ cat words | grep -e 'cat' -e 'dog'catcategoryacatconcatenatedoghello catdogdogdogdogdogdogdogdogdog
等价写法:
[yuxb@controller lab 19:09:00]$ cat words | egrep 'cat|dog'catcategoryacatconcatenatedoghello catdogdogdogdogdogdogdogdogdog
-f
作用:从文件读取模式,每行一个
示例:
[yuxb@controller lab 19:09:39]$ echo -e 'cat\ndog' > pattens_file[yuxb@controller lab 19:09:40]$ cat pattens_filecatdog[yuxb@controller lab 19:09:47]$ cat words | grep -f pattens_filecatcategoryacatconcatenatedoghello catdogdogdogdogdogdogdogdogdog
提示:模式文件就像你手写的“查找清单”,每行一条要查的文本。
-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'cathello 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'acathello 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'dogdogdog
匹配到前 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:cat4:category13:acat18:concatenate54:hello cat
左边数字是 匹配行第一个字符在文件中的字节位置,方便定位。
-n
显示行号
[yuxb@controller lab 19:17:43]$ cat words | grep -n 'cat'1:cat2:category3:acat4:concatenate11:hello cat
左边数字是 行号,方便查找。
-o
只输出匹配内容
[yuxb@controller lab 19:18:36]$ cat words | egrep -o '(dog){3}'dogdogdogdogdogdog
每个匹配结果单独一行。
-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/configgrep: /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, --copyuse copy instead of rename when shuffling files in -i mode-b, --binarydoes 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-dataseparate lines by NUL characters--helpdisplay this help and exit--versionoutput 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 sedI am www.twle.cnI am a no-work-menI am so handsome[yuxb@controller lab 10:22:07]$ sed '' data.txt I am studing sedI am www.twle.cnI am a no-work-menI am so handsome
示例2:从标准输入中读取数据
[yuxb@controller lab 10:22:12]$ sed ''# 输入hello world,并回车hello world# 输出hello worldhello 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 sedI am www.twle.cnI am a no-work-menI am so handsome# 如果只有一个命令,-e选项可以省略[yuxb@controller lab 10:24:07]$ sed '' data.txtI am studing sedI am www.twle.cnI am a no-work-menI am so handsome# -e 选项可以多次使用,1d是作用是删除第一行# 没有第五行,就没有删除效果[yuxb@controller lab 10:24:08]$ sed -e '1d' -e '2d' -e '5d' data.txtI am a no-work-menI am so handsome# 使用分号(;)分开多个命令[yuxb@controller lab 10:24:27]$ sed -e '1d;2d;5d' data.txtI am a no-work-menI 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 scripts1d2d5d[yuxb@controller lab 10:25:40]$ sed -f scripts data.txtI am a no-work-menI 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.txtI 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 3This is 4This is 5 [yuxb@controller lab 10:29:29]$ cat test | sed -n 'p'This is 1 This is 2 This is 3This is 4This 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 3This is 4This is 5
示例5: 连续输出,打印第2行以及后续两行
[yuxb@controller lab 10:32:40]$ cat test | sed -n '2,+2p'This is 2 This is 3This is 4
示例6: 隔行输出,打印第1行以及后续隔2行输出
[yuxb@controller lab 10:32:55]$ cat test | sed -n '1~2p'This is 1 This is 3This 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/bashba: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/bashbin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/falsemail: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/bashbin:x:1:1:bin:/bin:/bin/falsedaemon: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/bashbin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/falsemail:x:8:12:mail:/var/spool/mail:/bin/falseftp:x:14:11:ftp:/home/ftp:/bin/false&nobody:$:99:99:nobody:/:/bin/falsezhangy:x:1000:100:,,,:/home/zhangy:/bin/bashhttp:x:33:33::/srv/http:/bin/falsedbus:x:81:81:System message bus:/:/bin/falsehal:x:82:82:HAL daemon:/:/bin/falsemysql:x:89:89::/var/lib/mysql:/bin/falseaaa:x:1001:1001::/home/aaa:/bin/bashba:x:1002:1002::/home/zhangy:/bin/bashtest:x:1003:1003::/home/test:/bin/bash@zhangying:*:1004:1004::/home/test:/bin/bashpolicykit: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 2This 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/falsedaemon:x:2:2:daemon:/sbin:/bin/false==mail:x:8:12:mail:/var/spool/mail:/bin/falseftp:x:14:11:ftp:/home/ftp:/bin/false==&nobody:$:99:99:nobody:/:/bin/falsezhangy:x:1000:100:,,,:/home/zhangy:/bin/bash==http:x:33:33::/srv/http:/bin/falsedbus:x:81:81:System message bus:/:/bin/false==hal:x:82:82:HAL daemon:/:/bin/falsemysql:x:89:89::/var/lib/mysql:/bin/false==aaa:x:1001:1001::/home/aaa:/bin/bashba: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 tankzhangtankzhang: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 tankzhangtankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例3:加了-n
和p
后表示只打印那些发生替换的行(部分替换),下面的例子,不需要使用grep命令
[yuxb@controller ~ 10:45:23]$ sed -n 's/root/tankzhang/p' testtankzhang: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' testtankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例5:在第二行到第八行之间,替换以zhang开头的行,用ying来替换,并显示替换的行
[yuxb@controller ~ 10:47:31]$ sed -ne '2,8s/^zhang/ying/gp' testyingy: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' testyingy:x:1000:100:,,,:/home/yingy:/bin/bashba: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' testhello: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/bashgoodbay:x:81:81:System message bus:/:/bin/false
使用场景对比
写法 | 特点 | 适用场景 |
---|---|---|
; 分隔命令 | 简洁,但命令太多时可读性差 | 短小的一次性脚本 |
-e 多条命令 | 清晰,适合复杂脚本或多命令 | 推荐长期使用 |
插入
命令 | 作用 |
---|---|
a | 在匹配行 后 插入 |
i | 在匹配行 前 插入 |
c | 整行替换 |
a 在匹配行下面插入新行
将要插入的东西,插入到匹配行的下面
[yuxb@controller ~ 10:49:09]$ sed '/root/a====aaaa====' testroot:x:0:0:root:/root:/bin/bash====aaaa====bin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/falsemail:x:8:12:mail:/var/spool/mail:/bin/falseftp:x:14:11:ftp:/home/ftp:/bin/false&nobody:$:99:99:nobody:/:/bin/falsezhangy:x:1000:100:,,,:/home/zhangy:/bin/bashhttp:x:33:33::/srv/http:/bin/falsedbus:x:81:81:System message bus:/:/bin/falsehal:x:82:82:HAL daemon:/:/bin/falsemysql:x:89:89::/var/lib/mysql:/bin/falseaaa:x:1001:1001::/home/aaa:/bin/bashba:x:1002:1002::/home/zhangy:/bin/bashtest:x:1003:1003::/home/test:/bin/bash@zhangying:*:1004:1004::/home/test:/bin/bashpolicykit:x:102:1005:Po
i 在匹配行上面插入新行
将要插入的东西,插入到匹配行的上面
[yuxb@controller ~ 10:50:19]$ sed '/root/i====iiii====' test====iiii====root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/falsemail:x:8:12:mail:/var/spool/mail:/bin/falseftp:x:14:11:ftp:/home/ftp:/bin/false&nobody:$:99:99:nobody:/:/bin/falsezhangy:x:1000:100:,,,:/home/zhangy:/bin/bashhttp:x:33:33::/srv/http:/bin/falsedbus:x:81:81:System message bus:/:/bin/falsehal:x:82:82:HAL daemon:/:/bin/falsemysql:x:89:89::/var/lib/mysql:/bin/falseaaa:x:1001:1001::/home/aaa:/bin/bashba:x:1002:1002::/home/zhangy:/bin/bashtest:x:1003:1003::/home/test:/bin/bash@zhangying:*:1004:1004::/home/test:/bin/bashpolicykit: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/bashpolicykit:x:102:1005:Po
示例2: 删除4以后的行,包括第4行,把$当成最大行数就行了。
[yuxb@controller ~ 10:51:20]$ sed -e '4,$d' testroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/false
示例3: 删除包括false的行,或者包括bash的行,别忘了加\
[yuxb@controller ~ 10:52:33]$ sed -e '/\(false\|bash\)/d' testpolicykit:x:102:1005:Po
示例4: 删除从匹配root的行,到匹配以test开头的行,中间的行
[yuxb@controller ~ 10:52:33]$ sed -e '/root/,/^test/d' test@zhangying:*:1004:1004::/home/test:/bin/bashpolicykit: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 '=' test1root:x:0:0:root:/root:/bin/bash2bin:x:1:1:bin:/bin:/bin/false3daemon:x:2:2:daemon:/sbin:/bin/false4mail:x:8:12:mail:/var/spool/mail:/bin/false5ftp:x:14:11:ftp:/home/ftp:/bin/false6&nobody:$:99:99:nobody:/:/bin/false7zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash8http:x:33:33::/srv/http:/bin/false9dbus:x:81:81:System message bus:/:/bin/false10hal:x:82:82:HAL daemon:/:/bin/false11mysql:x:89:89::/var/lib/mysql:/bin/false12aaa:x:1001:1001::/home/aaa:/bin/bash13ba:x:1002:1002::/home/zhangy:/bin/bash14test:x:1003:1003::/home/test:/bin/bash15@zhangying:*:1004:1004::/home/test:/bin/bash16policykit: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/bash2:bin:x:1:1:bin:/bin:/bin/false3:daemon:x:2:2:daemon:/sbin:/bin/false4:mail:x:8:12:mail:/var/spool/mail:/bin/false5:ftp:x:14:11:ftp:/home/ftp:/bin/false6:&nobody:$:99:99:nobody:/:/bin/false7:zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash8:http:x:33:33::/srv/http:/bin/false9:dbus:x:81:81:System message bus:/:/bin/false10:hal:x:82:82:HAL daemon:/:/bin/false11:mysql:x:89:89::/var/lib/mysql:/bin/false12:aaa:x:1001:1001::/home/aaa:/bin/bash13:ba:x:1002:1002::/home/zhangy:/bin/bash14:test:x:1003:1003::/home/test:/bin/bash15:@zhangying:*:1004:1004::/home/test:/bin/bash16: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 test3root: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{Nw write.log # w write.log → 把整个模式空间写入 write.log}# 小写w写入包含模式中所有行[yuxb@controller ~ 10:57:04]$ cat write.logroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/bin/false# 大写W写入只包含模式中第一行[yuxb@controller ~ 10:57:05]$ vim scripts[yuxb@controller ~ 10:58:01]$ cat scripts 1{NW write.log}[yuxb@controller ~ 10:58:11]$ sed -n -f scripts test[yuxb@controller ~ 10:58:20]$ cat write.logroot:x:0:0:root:/root:/bin/bash
更改
整行替换。
作用
用新的内容替换匹配的整行。
在
sed
中有两种常用方式:
示例:root开头行替换出hello
# chello → 将匹配行整行替换为 hello[yuxb@controller ~ 10:58:49]$ sed '/^root/chello' testhellobin:x:1:1:bin:/bin:/bin/falsedaemon:x:2:2:daemon:/sbin:/bin/falsemail:x:8:12:mail:/var/spool/mail:/bin/falseftp:x:14:11:ftp:/home/ftp:/bin/false&nobody:$:99:99:nobody:/:/bin/falsezhangy:x:1000:100:,,,:/home/zhangy:/bin/bashhttp:x:33:33::/srv/http:/bin/falsedbus:x:81:81:System message bus:/:/bin/falsehal:x:82:82:HAL daemon:/:/bin/falsemysql:x:89:89::/var/lib/mysql:/bin/falseaaa:x:1001:1001::/home/aaa:/bin/bashba:x:1002:1002::/home/zhangy:/bin/bashtest:x:1003:1003::/home/test:/bin/bash@zhangying:*:1004:1004::/home/test:/bin/bashpolicykit: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.txt1) 张三 技术部 232) 李四 人力部 223) 王五 行政部 234) 赵六 技术部 245) 朱七 客服部 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.txt1) 张三 技术部 232) 李四 人力部 223) 王五 行政部 234) 赵六 技术部 245) 朱七 客服部 23
示例3: 输出特定隔行。
# /pattern/ 是 awk 最常用的 模式匹配方式[yuxb@controller ~ 11:25:43]$ awk '/张三/ { print }' employee.txt1) 张三 技术部 23[yuxb@controller ~ 11:25:59]$ awk '/张三/' employee.txt1) 张三 技术部 23
示例4: 统计满足特定条件的记录数。
[yuxb@controller ~ 11:26:05]$ awk '> /术/ { count=count+1 } > END { print "Count="count }' employee.txtCount=2# /术/ → 匹配包含“术”的行(如“技术部”)。# { count = count + 1 } → 每匹配一行,计数器 count 加 1。# END { print "Count=" count } → 在处理完所有行后打印结果。
示例5: 输出总长度大于 10 的行。
[yuxb@controller ~ 11:26:38]$ awk 'length($0)>10 { print $0 }' employee.txt1) 张三 技术部 232) 李四 人力部 223) 王五 行政部 234) 赵六 技术部 245) 朱七 客服部 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/bashecho $0echo $1echo $2echo $10echo ${10}echo $#echo $*echo $@echo "$@"
[yuxb@controller bin 15:01:59]$ bash showargs.sh {a..z}showargs.shaba0j26a b c d e f g h i j k l m n o p q r s t u v w x y za b c d e f g h i j k l m n o p q r s t u v w x y za 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/bashsystemctl $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 /rootls: 无法打开目录/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 COMMAND2696 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/hostnamecontroller.yuxb.cloud
Shell 内置变量命令
echo
echo命令参数选项:
-n,不换行输出内容。
-e,解析转义字符(见下面的字符)
转义字符:
\n,换行。
\t,制表符(tab)。
\b,退格。
[yuxb@controller bin 15:06:03]$ echo -n "laowang";echo laolilaowanglaoli[yuxb@controller bin 15:07:24]$ echo -e "laowang\nlaoli"laowanglaoli[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 haha12haha
read
[yuxb@controller bin 15:16:59]$ vim read.sh[yuxb@controller bin 15:17:13]$ cat read.sh #!/bin/shread -p "输入你想要说的话:" strecho "你想要说的话是:$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 $password123
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/shadowi can not read /etc/shadow[yuxb@controller bin 16:51:57]$ [ -d $path ] && echo $path is a directoryis a directory[yuxb@controller bin 16:52:36]$ ls $path666.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 $path666.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 existis 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.