我希望以下内容能起作用:
ls -l | grep '^.{38}<some date>'
它应该给我在修改时间中说了日期的文件。但这行不通。以下作品:
ls -l | grep '^.\{38\}<some date>'
'...'
是否应该关闭所有元字符的特殊含义?为什么我们必须逃脱括号?
答案 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
的其他一些问题)。