括号需要在单引号内使用\进行转义

时间:2018-12-15 18:13:27

标签: bash

我希望以下内容能起作用:

ls -l | grep '^.{38}<some date>'

它应该给我在修改时间中说了日期的文件。但这行不通。以下作品:

ls -l | grep '^.\{38\}<some date>'

'...'是否应该关闭所有元字符的特殊含义?为什么我们必须逃脱括号?

2 个答案:

答案 0 :(得分:1)

正则表达式.{38}(此处由grep解释)与正好是38个字符的任意字符串匹配。要匹配大括号,您需要对其进行转义。

.\{38\}

为了确保grep看到 准确的7个字符的序列,您需要用引号引起来,以使 shell 不在.{38}有机会看到报价之前执行报价删除并将其减少到grep


误解了问题,似乎grep使用的是 basic 正则表达式,其中未转义的花括号是文字字符,而转义的花括号引入了花括号表达式。在扩展正则表达式中,则相反。但是,无论哪种情况,单引号都会保护所有封闭的字符不受 shell 的特殊对待; grep是否特别对待他们是另一个问题。

答案 1 :(得分:1)

正则表达式语法有很多变体。默认情况下,grep使用“基本”(“ BRE”或“作废”)正则表达式语法,在这种语法中,必须将大括号转义以将其视为重复界限(在此尝试做的事情);如果没有转义符,它们将被视为文字字符。在“扩展”(“ ERE”或“现代”),Perl兼容(“ PCRE”)以及……嗯,几乎所有其他变体中,都是相反的:转义括号被视为文字字符,和未转义的定义重复边界。

grep '^.{38}<some date>'      # Matches any character followed by literal braces around "38"
grep '^.\{38\}<some date>'    # Matches 38 characters
grep -E '^.{38}<some date>'   # Matches 38 characters (-E invokes "extended" syntax)
egrep '^.{38}<some date>'     # Matches 38 characters (egrep uses "extended" syntax)

顺便说一句,括号是相同的:除非使用基本语法转义,否则为立即数;如果使用扩展语法转义,则为 if 。还有其他一些区别;参见the re_format man page。还有许多其他语法变体(与Perl兼容,等等)。重要的是要知道您使用的工具接受哪种变体,并为其格式化适当的RE。

BTW2,如@Charles Duffy在评论parsing ls output isn't a good idea中指出。在这种情况下,日期前的字符数将取决于其他字段的宽度(用户,组,大小),是一致的,因此跳过38个字符可能会跳过部分日期字段跳过不足。您最好在find-mtime测试中使用类似-mmin的东西,或者至少使用stat代替ls(因为您可以用格式字符串控制字段,例如,将日期放在行的开头)(但是stat仍然会有ls的其他一些问题)。