如何使用sed删除字符串中第1个与第2个空格之间的内容
问题原因及解决方案
你的写法错误原因
- 第一个写法
sed 's/\s.*\s/\s/'出错的核心是正则的贪婪匹配特性:.*会尽可能匹配最长的符合规则的内容,所以会从第一个空格一直匹配到整行最后一个空格的位置,并非你以为的匹配到第二个空格就停止。补充:
g参数的作用是控制一行内有多个匹配片段时是否全部替换,和正则匹配的贪婪性没有关系,你没有加g只是不会替换后续的匹配项,但第一个匹配项已经因为贪婪匹配覆盖了从第一个空格到最后一个空格的所有内容,所以结果不符合预期。 - 第二个写法
sed 's/(?<=\s).*(?=\s)//'出错是因为sed默认使用POSIX基本正则语法,不支持(?<=...)这种PCRE专属的后行断言语法,所以完全无法匹配到内容。如果要使用PCRE语法,GNU sed需要额外加-P参数开启,但该写法兼容性极差,不推荐使用。
正确实现方案
使用[^ ]*(匹配所有非空格字符)代替.*来限制匹配范围,就能精准匹配两个空格之间的内容,以下是全版本sed兼容的写法:
sed 's/^\([^ ]*\) [^ ]* /\1 /'
语法解释
^匹配行首位置\([^ ]*\)是第一个捕获组,匹配第一个空格之前的所有非空格内容- 随后匹配第一个空格
[^ ]*匹配第一个空格之后、第二个空格之前的所有非空格内容(也就是你需要删除的内容)- 随后匹配第二个空格
- 替换为
\1,即保留第一个捕获组的内容加一个空格,刚好删除中间的目标内容
效果测试
输入行:
>sp.A9L976 PSBA_LEMMI Photosystem II protein D1 organism=Lemna minor taxid=4472 gene=psbA
运行命令后输出:
>sp.A9L976 Photosystem II protein D1 organism=Lemna minor taxid=4472 gene=psbA
可选简化写法
如果使用GNU sed或者macOS新版sed,可以加-E参数开启扩展正则,省略捕获组的转义符:
sed -E 's/^([^ ]*) [^ ]* /\1 /'
内容的提问来源于stack exchange,提问作者han5000
相关产品推荐
相关产品推荐

