regex - 神秘的 sed 命令语法困惑

标签 regex unix sed

谁能解释一下这个 sed 命令在这里是如何工作的?

pkg info | sed -e 's/\([^.]*\).*/\1/' -e 's/\(.*\)-.*/\1/'

此命令从包中删除版本号并像这样打印到标准输出中

yajl-2.1.0                     Portable JSON parsing and serialization library in ANSI C
youtube_dl-2018.12.03          Program for downloading videos from YouTube.com
zathura-0.4.1                  Customizable lightweight pdf viewer
zathura-pdf-poppler-0.2.9_1    Poppler render PDF plugin for Zathura PDF viewer
zip-3.0_1                      Create/update ZIP files compatible with PKZIP
zsh-5.6.2                      The Z shell

然后变成这个

yajl
youtube_dl
zathura
zathura-pdf-poppler
zip
zsh

但我很难理解 ([^.]*\).* \(.*\)-.* 部分。我理解 \-es 的大小写。但是这些通配符在这里看起来非常神秘。

最佳答案

在你的正则表达式 ([^.]*\).* 中,( 实际上是 \( 是捕获的开始group 然后 [^.]* 捕获除文字点之外的每个字符,* 表示零个或多个,然后 \) 是我们开始的 group 的结束标记,然后 .* 捕获捕获 group1 后剩下的任何内容。

\(.*\)-.* 正则表达式的解释类似,其中 \(.*\) 将在捕获 时贪婪地捕获所有内容group 但将在最后一个连字符 - 处停止,然后将匹配连字符和进一步的 .* 将匹配剩余的文本。

youtube_dl-2018.12.03为例进行说明。

在这里,\([^.]*\) 将捕获点之前的所有内容,因此它将捕获 youtube_dl-2018,然后是剩余的 。* 将捕获 .12.03。然后它将被 \1 替换,这意味着 youtube_dl-2018 将被传递到下一个正则表达式 -e 's/\(.*\)-。 */\1/'.

然后在你的第二个正则表达式中,\(.*\)-.*\(.*\) 将捕获 youtube_dl 和放入 group1 因为后面有一个连字符和 .* 将捕获剩余的文本,即 2018。由于它被替换为 \1 因此最终文本将变为 youtube_dl

看到你的数据,我相信你也可以将你的命令简化为这个,因为你在 sed 命令中的第一个正则表达式似乎是多余的。试试下面的命令,看看它是否输出相同的结果?

pkg info | sed -e 's/\(.*\)-.*/\1/'

你只能使用这个简化的命令,因为你的数据中没有一个在 - 之前包含一个 .,否则你应该使用你自己的命令,它有两个 sed 规则。

此外,另一方面,如果您使用 -r(或 -E 用于 OS X),对于扩展正则表达式,您不需要转义括号,您可以将正则表达式写为,

pkg info | sed -r 's/([^.]*).*/\1/' -r 's/(.*)-.*/\1/'

关于regex - 神秘的 sed 命令语法困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53976504/

相关文章:

regex - Javascript regex.match 有缺陷?

linux - 当有人 cd 到特定目录时如何执行某些命令

bash - sed multiline 删除第一次出现模式之前的所有内容

javascript正则表达式匹配2个html评论标签之间的所有内容

regex - 用于打印模式 1、搜索并打印从模式 2 到模式 3 的所有行以及打印模式 4 的 Bash 脚本

java - 如何使用 Java 正则表达式从路径中删除 id?

linux - 发送电子邮件后 Jenkins 运行 Shell 脚本

c - 如何杀死一个pid不断变化的进程?

sed 删除\t 之后行中的所有内容

macos - 检索两篇文本的部分共同内容