![grep 与 sed 中的正则表达式](https://linux22.com/image/231174/grep%20%E4%B8%8E%20sed%20%E4%B8%AD%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.png)
我正在尝试查找并替换文本文件中以 a 开头的所有行单一空间然后是任何字符。
终于让正则表达式在 grep 上工作了grep -E '^ .*$*' Contacts.vcf >> t.txt
然后,当在 sed 上使用它时,它不会sed 's/^ .*$//g' Contacts.vcf > tt.txt
- 我得到所有行(无论开头是否有空格)。我已经尝试\s{1}
将所有内容放入()
但无法使其工作。
我最初在 Windows 上使用 PowerShell 尝试时遇到了同样的问题。我觉得我错过了平台之间正则表达式的细节(?)。
如何强制正则表达式仅查找以单个空格开头的行?
答案1
grep
您可以通过实现“以空格开头,后跟任何字符”来简化
grep '^ .'
如果你只想“从空间开始”那就更容易了
grep '^ '
现在sed
,它变化输入并显示所有内容。要让sed
行为更像grep
它,需要-n
旗帜和p
命令; -n
意味着默认情况下不显示输出,p
意味着“打印这一行”
例如
sed -n '/^ /p'
将显示以空格开头的所有行,类似地
sed -n '/^ ./p'
将显示以空格开头并后跟任何其他字符的所有行
编辑
根据其他评论,您的目标似乎是删除以空格开头的行,并且您想用来sed
执行此操作。
在这种情况下
sed -i '/^ /d'
基本上,“搜索以空格开头的行并将其删除”
例如
$ cat x
hello
there
everyone
$ sed -i '/^ /d' x
$ cat x
hello
everyone
答案2
如果要删除所有以一个空格开头的行。
您可以将 grep 与以下命令一起使用-v
:
grep -v -E '^ .*$' Contacts.vcf > tt.txt
-v, --invert-match
Invert the sense of matching, to select non-matching lines.
并且,“$”代表行结束。
其后不应有任何字符。
因此,“$”后面的星号应该是没有意义的。
答案3
你说:
我试图查找并替换文本文件中以单个空格开头然后是任何字符的所有行。
为您列出的项目添加正则表达式构造,即变为:
我试图查找并替换文本文件中
^
以单个空格 ( )开头 () 的所有行,然后是任何字符(技术上
..*
在 BRE 或.+
ERE 中,但是,因为 1 个字符是“任何字符”,当您只是尝试打印包含匹配字符串的整行而不是打印特定的匹配字符串,您所需要的只是.
任何正则表达式风格)。
然后使用这些工具的任何版本直接实现如下:
grep '^ .'
sed -n '/^ ./p'
awk '/^ ./'
自从:
^
= 字符串的开头(在本例中为当前输入行)。= 一个空格。如果您指的是任何空白字符,则使用
[[:space:]]
or[[:blank:]]
或者[ \t]
如果您只是指空白或制表符。.
= 任何字符。
您使用的命令grep
是:
grep -E '^ .*$*'
存在以下问题:
-E
使grep
接受 ERE 作为正则表达式而不是默认的 BRE,但是您的正则表达式中没有任何内容不是基本的正则表达式语法,因此-E
没有做任何有用的事情。$
表示缓冲区结束(在本例中为输入行结束),而*
是 0 次或多次重复元字符,因此$*
表示“缓冲区结束的零次或多次重复” - 根据定义,结束不能超过 1 个您正在处理的缓冲区因此毫无意义,并且实际上是每个 POSIX 未定义的行为。.*
意思是“任何字符的零次或多次重复”,但您的要求是该位置至少有 1 个字符,所以这*
是错误的。您可以.+
在 ERE 或..*
BRE 中使用表示“一个或多个”,但不需要“或多个”,因为单个字符.
足以满足您的要求,即存在 1 个或多个字符(如果有 1 个 - 足够好) )。.*
不会匹配空格后的任何字符,但我假设“任何字符”是指至少 1 个字符。
您使用的命令sed
是:
sed 's/^ .*$//g'
存在以下问题:
- grep 和 sed 默认情况下都在 BRE 上运行,当使用
-E
.如果您认为需要-E
grep regexp (实际上不需要),那么您-E
也应该使用 sed 来调用。 - 您的 grep 正则表达式
*
末尾有 a 。再说一遍,如果您认为 grep 需要它(实际上不需要),那么您也应该在 sed regexp 中拥有它。 - 就像你的 grep 正则表达式一样,
.*$
除非.
你真的不想在空格后允许任何字符,否则它就可以,.?
但.*
也可以。 grep
因全局匹配正则表达式并打印结果的命令g/re/p
而命名。ed
鉴于此,很明显 grep 默认情况下只会打印与正则表达式匹配的行。sed
是一个流编辑器,因此它会执行ed
您给它的任何命令(以及现在的其他命令),但就像任何编辑器一样,如果您不告诉它,它不会删除任何内容,因此默认情况下它会打印每个输入行。要不sed
这样做,您需要使用-n
(“默认情况下不打印”)来调用它,然后您需要使用p
脚本中的指令告诉它打印特定行。- sed 命令末尾
g
的 告诉 sed 每次出现在输入行中时都匹配正则表达式,但是您^
只能在行开头匹配一次,并且$
只能在行末尾匹配一次其中足以使正则表达式每行只能匹配一次,因此g
在命令末尾放置 a 告诉 sed 尝试多次匹配正则表达式没有任何用处。
其他注意事项:
- 只有 sed 的 GNU 和 BSD 变体支持
-E
ERE,所有其他 sed 变体仅支持 BRE。 - 关于“我已经尝试过
\s{1}
” -是PCRE 中\s
POSIX 字符类的简写,而不是 POSIX BRE 或 ERE 中的简写。[[:space:]]
GNU sed 和 GNU grep 将接受\s
BRE 或 ERE、YMMV 及其非 GNU 变体或使用 BRE 和/或 ERE 而不是 PCRE 进行操作的任何其他工具。