首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用?使用sed

使用?使用sed
EN

Stack Overflow用户
提问于 2010-12-04 01:30:49
回答 7查看 14.9K关注 0票数 28

我只想得到一个可能是也可能不是gzip的文件号。但是,sed中的正则表达式似乎不支持?。这是我尝试过的:

echo 'file_1.gz'|sed -n 's/.*_\(.*\)\(\.gz\)?/\1/p'

却什么也没有返回。然后,我向正在分析的字符串添加了一个?

echo 'file_1.gz?'|sed -n 's/.*_\(.*\)\(\.gz\)?/\1/p'

并得到了:

1

所以,看起来在大多数正则表达式中使用的?在sed中不受支持,对吧?那么,我只想让sed为file_1file_1.gz提供一个1。如果执行时间很关键,那么在bash脚本中实现这一点的最佳方法是什么?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-12-04 01:34:55

x?等效的是\(x\|\)

但是,许多版本的sed支持启用“扩展正则表达式”的选项,其中包括?。在GNU中,这个标志是-r。请注意,这也会将未转义的括号更改为进行分组。例如:

代码语言:javascript
运行
复制
echo 'file_1.gz'|sed -n -r 's/.*_(.*)(\.gz)?/\1/p'

实际上,在您的正则表达式中有另一个bug,那就是如果有".gz“的话,括号中贪婪的.*将会吞噬掉它。据我所知,sed没有一个非贪婪的等价物*,但是你可以使用|来解决这个问题。sed (和许多其他正则表达式实现)中的|将使用最左边的匹配,所以您可以这样做:

代码语言:javascript
运行
复制
echo 'file_1.gz'|sed -r 's/(.*_(.*)\.gz)|(.*_(.*))/\2\4/'

这会尝试与.gz匹配,并且只有在没有它的情况下才会尝试,如果不起作用。实际上,组2或组4中只有一个会存在(因为它们位于同一|的两端),所以我们只需将它们连接起来就可以得到我们想要的值。

票数 47
EN

Stack Overflow用户

发布于 2013-03-15 07:57:02

如果您正在寻找问题中给出的特定示例的答案,或者为什么它不正确地使用? (不管语法如何),请参阅the answer by Laurence Gonsalves

如果您正在寻找通用问题的答案,即为什么?没有像您预期的那样在sed中显示其特殊含义:

默认情况下,sed使用“POSIX basic正则表达式语法”,因此必须将问号转义为\?以应用其特殊含义,否则它将匹配文字问号。作为另一种选择,您可以使用-r--regexp-extended选项来使用“扩展正则表达式语法”,它颠倒了转义和非转义特殊字符(包括? )的含义。

用GNU sed文档的话说(在Linux上运行'info sed‘查看):

基本正则表达式和扩展正则表达式之间的唯一区别是几个字符的行为:'?‘、'+’、圆括号和花括号('{}')。如果您希望它们表现为特殊字符,则基本正则表达式需要对它们进行转义,而在使用扩展正则表达式时,如果希望它们与文字字符匹配,则必须对它们进行转义。

并解释了该选项:

-r --regexp-extended

使用扩展正则表达式,而不是基本正则表达式。扩展正则表达式是‘`egrep’接受的那些;它们可以更清晰,因为它们通常具有较少的反斜杠,但它们是GNU扩展,因此使用它们的脚本不可移植。

更新

较新版本的GNU sed现在这样说:

-E -r --regexp-extended

使用扩展正则表达式,而不是基本正则表达式。扩展正则表达式是'egrep‘接受的正则表达式;它们可以更清晰,因为它们通常具有较少的反斜杠。从历史上看,这是一个GNU扩展,但是'-E‘扩展名后来被添加到POSIX标准(http://austingroupbugs.net/view.php?id=528)中,因此使用'-E’表示可移植性。GNU sed多年来一直接受'-E‘作为未记录的选项,*BSD sed也接受'-E’已有多年,但使用'-E‘的脚本可能无法移植到其他较旧的系统。

因此,如果您需要保持与古老的GNU sed的兼容性,请坚持使用-r。但是,如果您希望在更现代的系统上获得更好的跨平台可移植性(例如,Linux+Mac支持),请使用-E (但请注意,GNU sed和BSD sed之间仍然存在一些怪癖和差异,因此您必须确保您的脚本在任何情况下都是可移植的)。

票数 9
EN

Stack Overflow用户

发布于 2010-12-04 01:34:36

代码语言:javascript
运行
复制
echo 'file_1.gz'|sed -n 's/.*_\(.*\)\?\(\.gz\)/\1/p'

很管用。你必须将返回值放在正确的位置,并且必须避开它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4348166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档