在本章中,我们将详细讨论Unix中使用SED的正则表达式,正则表达式由几种不同的Unix命令使用,包括 ed , sed , awk , grep 和 vi 。
在开始之前, 我们最好先备份一下/etc/passwd 文件。通过如下方式通过管道调用sed:
$cat /etc/passwd | sed Usage: sed [OPTION]... {script-other-script} [input-file]... -n, --quiet, --silent suppress automatic printing of pattern space -e script, --expression=script ...............................
cat 命令通过管道将/etc/passwd 的内容转储到 sed 的模式空间中,模式空间是sed用于其操作的内部工作缓冲区。
以下是sed的一般语法-
/pattern/action
在这里, pattern 是正则表达式,而 action 是下表中给出的命令之一。如果省略 pattern ,则对每行执行 action ,如上所述。
包围模式的斜杠(/)是必需的,因为它们用作分隔符。
Sr.No. | Range & 描述 |
---|---|
1 | p 打印行 |
2 | d 删除行 |
3 | s/pattern1/pattern2/ 用pattern2替换第一次出现的pattern1 |
现在,我们使用单字母 d 删除sed的所有行。
$cat /etc/passwd | sed 'd' $
以下命令与上一个示例完全相同,但没有cat命令-
$sed -e 'd' /etc/passwd $
sed还支持地址(Address),地址可以是文件中的特定位置,也可以是应应用特定编辑命令的范围。
以下命令将基本地址添加到您一直在使用的sed命令中-
$cat /etc/passwd | sed '1d' |more daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh $
请注意,在删除编辑命令之前添加了数字1,这指示sed在文件的第一行执行编辑命令。在此示例中,sed将删除/etc/password 的第一行并打印文件的其余部分。
现在,我们将了解如何使用 sed 地址范围。那么,如果要从文件中删除多行呢?您可以使用sed指定地址范围,如下所示:
$cat /etc/passwd | sed '1, 5d' |more games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh $
上面的命令将应用于从1到5的所有行。这将删除前五行。
尝试以下地址范围-
Sr.No. | Range & 描述 |
---|---|
1 | '4,10d' 从第4 到第10 的行被删除 |
2 | '10,4d' 由于sed不能反向运行,因此仅删除第10 行 |
3 | '4,+5d' 这与文件中的第4行匹配,删除该行,继续删除接下来的5行,然后停止删除并打印其余部分 |
4 | '2,5!d' 这会删除所有内容,除了从第2 nd 行开始直到第5 th 行 |
5 | " 1〜3d" 这将删除第一行,在接下来的三行上移动,然后删除第四行, Sed继续应用此模式,直到文件结束。 |
6 | '2〜2d' 这告诉sed删除第二行,移至下一行,删除下一行,然后重复直到到达文件末尾 |
7 | '4,10p' 打印从第4 到第10 的行 |
8 | '4,d' 这会产生语法错误 |
9 | ',10d' 这也会产生语法错误 |
注意-使用p操作时,应使用-n选项以避免重复行打印。 检查以下两个命令之间的区别-
$cat /etc/passwd | sed -n '1,3p' Check the above command without -n as follows - $cat /etc/passwd | sed '1,3p'
用 s 表示的替换命令将用您指定的任何其他字符串替换您指定的任何字符串。
以下命令用字符串 learnfk 替换字符串 root 的行中的第一个匹配项。
$cat /etc/passwd | sed 's/root/learnfk/' learnfk:x:0:0:root user:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh ..........................
重要的是要注意,sed仅替换行中的第一个匹配项。如果字符串根在一行中出现多次,则仅第一个匹配项将被替换。
为了使sed执行全局替换,请在命令末尾添加字母 g ,如下所示:
$cat /etc/passwd | sed 's/root/learnfk/g' learnfk:x:0:0:learnfk user:/learnfk:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh ...........................
除了 g 标志之外,还可以传递许多其他有用的标志,并且您一次可以指定多个。
Sr.No. | Flag & 描述 |
---|---|
1 | g 替换所有匹配。 |
2 | NUMBER 仅替换NUMBER th 个匹配项 |
3 | p 如果进行了替换,则打印匹配内容 |
4 | w FILENAME 如果进行了替换,则将输出写入FILENAME |
5 | I 或 i 以不区分大小写的方式匹配 |
6 | M 或 m 除了特殊正则表达式字符^和$的正常行为外,此标志还会导致^匹配换行符之后的空字符串,以及$匹配换行符之前的空字符串。 |
假设您必须对包含正斜杠字符的字符串进行替换。在这种情况下,可以通过在 s 之后提供指定的字符来指定其他分隔符。
$cat /etc/passwd | sed 's:/root:/learnfk:g' learnfk:x:0:0:learnfk user:/learnfk:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh
在上面的示例中,我们使用:作为定界符而不是斜杠/,因为我们搜索/root 而不是简单的 root。
使用空的替换字符串从/etc/passwd 文件中完全删除根字符串-
$cat /etc/passwd | sed 's/root//g' :x:0:0::/:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh
如果只想在第10行将字符串 sh 替换为字符串 quiet ,则可以按以下方式指定它-
$cat /etc/passwd | sed '10s/sh/quiet/g' root:x:0:0:root user:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/quiet
同样,要进行地址范围替换,您可以执行以下操作-
$cat /etc/passwd | sed '1,5s/sh/quiet/g' root:x:0:0:root user:/root:/bin/quiet daemon:x:1:1:daemon:/usr/sbin:/bin/quiet bin:x:2:2:bin:/bin:/bin/quiet sys:x:3:3:sys:/dev:/bin/quiet sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh
从输出中可以看到,前五行的字符串 sh 更改为 quiet ,但其余各行保持不变。
您将使用p选项和-n选项一起打印所有匹配的行,如下所示:
$cat testing | sed -n '/root/p' root:x:0:0:root user:/root:/bin/sh [root@ip-72-167-112-17 learnfk]# vi testing root:x:0:0:root user:/root:/bin/sh daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh
在匹配模式时,您可以使用正则表达式来提供更大的灵活性。
检查以下示例,该示例匹配以 daemon 开头的所有行,然后将其删除-
$cat testing | sed '/^daemon/d' root:x:0:0:root user:/root:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh
以下是删除所有以 sh 结尾的行的示例-
$cat testing | sed '/sh$/d' sync:x:4:65534:sync:/bin:/bin/sync
下表列出了四个在正则表达式中非常有用的特殊字符。
Sr.No. | Character & 描述 |
---|---|
1 | ^ 匹配行首 |
2 | $ 匹配行尾 |
3 | . 匹配任何单个字符 |
4 | * 匹配零个或多个前一个字符 |
5 | [chars] 匹配chars中给定的任何字符,其中chars是字符序列。您可以使用-字符来指示字符范围。 |
再看一些表达式来演示元字符的用法。如,以下模式-
Sr.No. | Expression & 描述 |
---|---|
1 | /a.c/ 匹配包含a + c,a-c,abc,match和a3c之类的字符串的行 |
2 | /a * c/ 匹配相同的字符串以及诸如 ace , yacc 和 arctic 之类的字符串 |
3 | /[tT]是/ 匹配字符串 The 和 the |
4 | /^ $/ 匹配空白行 |
5 | /^.*$/ 匹配整行 |
6 | /*/ 匹配一个或多个空格 |
7 | /^ $/ 匹配空白行 |
下表显示了一些常用的字符集-
Sr.No. | Set & 描述 |
---|---|
1 | [a-z] 匹配单个小写字母 |
2 | [A-Z] 匹配单个大写字母 |
3 | [a-zA-Z] 匹配一个字母 |
4 | [0-9] 匹配一个数字 |
5 | [a-zA-Z0-9] 匹配一个字母 or 数字 |
regexps 通常可以使用一些特殊的关键字,特别是使用 regexps 的GNU实用程序。这些对于sed正则表达式非常有用,因为它们简化了事情并提高了可读性。
如,字符 a到z 和字符 A到Z 构成了这类具有关键字 [[:alpha:]]
使用字母字符类关键字,此命令仅打印 /etc/syslog.conf 文件中以字母开头的行-
$cat /etc/syslog.conf | sed -n '/^[[:alpha:]]/p' authpriv.* /var/log/secure mail.* -/var/log/maillog cron.* /var/log/cron uucp,news.crit /var/log/spooler local7.* /var/log/boot.log
下表是GNU sed中可用字符类关键字的完整列表。
Sr.No. | Character Class & 描述 |
---|---|
1 | [[::alnum:]] 字母数字[a-z A-Z 0-9] |
2 | [[::alpha:]] 字母[a-z A-Z] |
3 | [[::blank:]] 空白字符(空格或制表符) |
4 | [[::ctrl:]] 控制字符 |
5 | [[:digit:]] 数字[0-9] |
6 | [[::graph:]] 任何可见字符(不包括空格) |
7 | [[::lower:]] 小写字母[a-z] |
8 | [[::print:]] 可打印字符(非控制字符) |
9 | [[:punct:]] 标点符号 |
10 | [[::space:]] 空格 |
11 | [[::upper:]] 大写字母[A-Z] |
12 | [[:xdigit:]] 十六进制数字[0-9 a-f A-F] |
sed元字符&表示匹配的模式的内容。 如,假设您有一个名为phone.txt的文件,其中包含完整的pady number,如以下内容-
5555551212 5555551213 5555551214 6665551215 6665551216 7775551217
您希望将区域代码(前三位数字)用括号括起来,以便于阅读。为此,您可以使用&替换字符-
$sed -e 's/^[[:digit:]][[:digit:]][[:digit:]]/(&)/g' phone.txt (555)5551212 (555)5551213 (555)5551214 (666)5551215 (666)5551216 (777)5551217
在模式部分中,您要匹配前3位数字,然后使用&将3位数字替换为括号。
您可以在单个sed命令中使用多个sed命令,如下所示-
$sed -e 'command1' -e 'command2' ... -e 'commandN' files
这里的 command1 至 commandN 是前面讨论的类型的sed命令。这些命令应用于文件给定的文件列表中的每一行。
使用相同的机制,我们可以编写上面的pady number示例,如下所示:
$sed -e 's/^[[:digit:]]\{3\}/(&)/g'\ -e 's/)[[:digit:]]\{3\}/&-/g' phone.txt (555)555-1212 (555)555-1213 (555)555-1214 (666)555-1215 (666)555-1216 (777)555-1217
注–在上面的示例中,我们没有用\{3\}替换字符类关键字[[:digit:]]三次,而是将其替换为\{3\},这意味着前面的正则表达式被匹配了3次。 我们还使用\给出了换行符,必须在运行命令之前将其删除。
祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)