隐秘sed命令语法混乱

时间:2018-12-30 09:30:24

标签: 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的情况。但是这些通配符在这里似乎很神秘。

3 个答案:

答案 0 :(得分:5)

在您的正则表达式([^.]*\).*中,实际上是(的{​​{1}}是捕获 group 的开始,然后\(捕获除文字点,[^.]*表示零或多个,然后*是我们开始的 group 的结束标记,然后\)捕获捕获< em> group1 。

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

为了举例说明,让我们以.*为例。

在这里,youtube_dl-2018.12.03将捕获所有内容,直到点为止,因此它将捕获\([^.]*\),然后其余的youtube_dl-2018将捕获.*。然后将其替换为.12.03,这意味着\1将被传递到下一个正则表达式youtube_dl-2018

然后在第二个正则表达式-e 's/\(.*\)-.*/\1/'\(.*\)-.*中捕获\(.*\)并放入 group1 ,因为在此之后有一个连字符和{{1} }将捕获剩余的文本youtube_dl。并且由于它被.*取代,因此最终文本将变成2018

我相信,看到数据后,您还可以简化命令,因为\1命令中的第一个正则表达式似乎很多余。试试下面的命令,看看是否输出相同的结果?

youtube_dl

您只能使用此简化命令,因为您的任何数据都不会在sed之前包含pkg info | sed -e 's/\(.*\)-.*/\1/' ,否则,您应该使用具有两个.规则的自己的命令。

另外,请注意,如果您使用-(对于OS X X是 -E )对于扩展正则表达式,则不需要逃避括号,您可以将正则表达式写为

sed

答案 1 :(得分:2)

很难说:
删除所有以点或连字符开头的子字符串。
匹配并记住定界符之前的部分。
替代方法:

# Incorrect: removes from first, not last hypen:
#    pkg info | sed 's/[-.].*//'
#    pkg info | cut -d "-" -f1 | cut -d"." -f1
#    pkg info | awk -F "-|[.]" '{print $1}'
# The dot is not needed when you remove the substring starting with the last hypen
pkg info | sed 's/-[^-]*$//'
pkg info | rev | cut -d"-" -f2- | rev
pkg info | awk -F "[.]" '{print $1}' | awk -F "[-]" -vOFS='-' 'NF>1 { NF--;print;}'

答案 2 :(得分:0)

    在控制台上运行的
  1. Silly不可见文本 GNU grep方法, 但是如果发送到文件或通过管道传递到过滤器,则会失败:

    pkg info | GREP_COLORS='ms=30;30;30' grep '\-[^-]*\s.*$'
    

    工作原理:grep用于查找一个连字符之前的最后一个连字符 空间以及此后的所有内容,(我们不需要的所有内容 以查看),grep以突出显示的颜色显示,如 GREP_COLORS个环境变量。自突出颜色 30;30;30是黑色字体(在黑色背景上),不需要 文字不可见。

    如果终端背景已经是黑色,则GREP_COLORS='ms=30 足够。

  2. 基于 not
  3. sed方法会打印grep regex

    pkg info | sed 's#\(^.*\)\(-[^-]*[[:space:]].*$\)#\1#'
    

    ...此方法 可以发送到管道和过滤器。使用 GNU sed的较短版本:

    pkg info | sed 's#\(^.*\)\(-.*\s.*\)#\1#'