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

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

解释:

  • . → 任意字符

  • \. → 真正的小数点

  • ⚠️ 小白注意:转义符可以让符号按“原义”匹配。


|(必须用 egrepgrep -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固定字符串匹配,不解析正则
-PPerl 正则表达式,语法更丰富

匹配模式来源

选项含义
-e PATTERN直接指定模式
-f FILE从文件中读取模式,每行一个

忽略大小写 / 完整匹配

选项含义
-i忽略大小写
-w匹配完整单词
-x整行完全匹配

输出控制

选项含义
-v反转匹配,显示不匹配的行
-m NUM最多匹配 NUM 行
-c只显示匹配行数
-b显示字节偏移量
-n显示行号
-o只输出匹配的文本
-q静默模式,不输出内容,只返回退出状态
-s抑制错误信息

grep 命令选项实例

模式选择和解释选项

-Eegrep
  • 作用:支持扩展正则表达式,能用 + ? | {} 等高级语法

  • 示例

[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

忽略大小写后,CBtcBtcbt 都能匹配。


-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 的操作命令(如 pds

  • 文件:要处理的文本文件,如果省略则默认从标准输入读取

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 命令作用的行,可以是行号、范围、正则匹配等。

  • 命令:如 pds 等。

示例
[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 '/模式/ 命令' 文件
  • /模式/:正则表达式,用来匹配行

  • 命令:对匹配到的行执行操作,如 pds

准备文件

[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:加了-np后表示只打印那些发生替换的行(部分替换),下面的例子,不需要使用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:加了-npg后表示只打印那些发生替换的行(全部替换)

[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.​
http://www.dtcms.com/a/340397.html

相关文章:

  • CentOS 7/8 搭建 Samba 文件共享服务并与Windows无缝集成
  • centos配置ip地址不生效
  • 关于多个el-input的自动聚焦,每输入完一个el-input,自动聚焦到下一个
  • 基于SpringBoot的校园跳蚤市场二手交易管理系统【2026最新】
  • 如何删除三星手机上的所有内容(5 种解决方案)
  • 微美全息(NASDAQ:WIMI):以区块链+云计算混合架构,引领数据交易营销科技新潮流
  • 2026 济南淀粉深加工展览会亮点:玉米科技与未来产业发展
  • Vue3 element ui 给表格的列设置背景颜色
  • vue3源码reactivity响应式之数组代理的方法
  • 解决前端项目启动时找不到esm文件的问题
  • 微算法科技(NASDAQ: MLGO)引入高级区块链DSR算法:重塑区块链网络安全新范式
  • AI时代SEO关键词优化新策略
  • 设计模式1-单例模式
  • 梯度提升决策树(GBDT):从原理到实战,掌握结构化数据建模的核心利器
  • Python入门第13课:数据可视化入门,用Matplotlib绘制你的第一张图表
  • Java 线程池ThreadPoolExecutor源码解读
  • 算法 ----- 链式
  • Day 30 模块和库导入
  • mapbox高阶,结合threejs(threebox)添加建筑glb模型,添加阴影效果,设置阴影颜色和透明度
  • 力扣 30 天 JavaScript 挑战 第36天 第8题笔记 深入了解reduce,this
  • CorrectNav——基于VLM构建带“自我纠正飞轮”的VLN:通过视觉输入和语言指令预测导航动作,且从动作和感知层面生成自我修正数据
  • 【Linux】系统部分——磁盘存储结构与文件系统
  • C++八股 —— 设计模式
  • wpf之ComboBox
  • DRF序列化器
  • DeepSeek V3.1 完整评测分析:2025年AI编程新标杆
  • ⭐CVPR2025 给3D高斯穿 “UV 衣” 框架[特殊字符]
  • 路由器NAT的类型测定
  • KubeBlocks AI:AI时代的云原生数据库运维探索
  • Redux 核心概念详解