为什么\s+
不起作用?
先说原因和正确写法,有三,
1,sed 版本不匹配,GUN 不支持,需要\s\+,加号前加斜杠,正确写法:echo "a b" | sed "s/\s\+/_/g"
2, sed -e "s/\s+/_/g" 小写的-e没有正则效果, 正确写法 sed -e "s/\s\+/_/g"
3, sed -E "s/\s\+/_/g" 大写的-E本身正则,无需加号前加斜杠 正确写法 sed -E "s/\s+/_/g"
详细解释
\s+
语法是POSIX标准正则表达式的一部分,但在 sed
中,它的支持依赖于具体的 sed
实现版本。
-
标准
sed
的限制:sed
默认遵循 POSIX 标准,而在 POSIX 正则表达式中,\s
并不被支持用来匹配空白字符。
例如:- GNU
sed
和部分扩展版本支持\s
(代表空格)。 - 但在一些非扩展版本中,
\s
被视为普通字符,导致无法匹配空格。
- GNU
-
+
的限制:+
在 POSIX 标准sed
中并不是正则表达式的原生符号(只能使用\{1,\}
来表示 "一个或多个")。
在 GNUsed
版本中,+
需要使用反斜杠\+
才能生效。
更多兼容方案
为了在各种 sed
版本中保持兼容性,推荐使用以下写法:
1. 用 [[:space:]]\+
替代 \s+
echo "test/myfolder # 测试 字符串" | sed -e "s/[[:space:]]\+//g"
[[:space:]]
:表示匹配任何空白字符(包括空格、制表符\t
等)。\+
:GNUsed
中的扩展语法,表示匹配一个或多个前面的字符。
2. 兼容非 GNU sed
的写法
如果你使用的是较老版本的 sed
(不支持 \+
),可以用 {1,}
来替代 \+
:
echo "test/myfolder # 测试 字符串" | sed -e "s/[[:space:]]\{1,\}//g"
{1,}
:表示匹配一个或多个空白字符。
3. 如果需要 \s+
支持
- 确保使用 GNU
sed
,并调用sed -E
选项以开启扩展正则表达式支持:
echo "test/myfolder # 测试 字符串" | sed -E "s/\s+//g"
-E
:启用扩展正则表达式模式(无需反斜杠,例如\s+
就可以直接使用)。
结论
\s+
不是 POSIX 标准的一部分,原生sed
不支持。[[:space:]]\+
或[[:space:]]\{1,\}
是在sed
中替代\s+
的最佳选择。- 使用
sed -E
可启用扩展正则表达式,简化正则语法。
推荐写法:
echo "test/myfolder # 测试 字符串" | sed -E "s/[[:space:]]+//g"
或者:
echo "test/myfolder # 测试 字符串" | sed -e "s/[[:space:]]\+//g"
那怎么确认我用的是POSIX 还是GNU,因为刚刚\s+不成功,\s\+就成功了,而且\+的\有时不需要也可以
确认当前使用的是 POSIX sed
还是 GNU sed
,可以通过以下方式来判断和验证:
1. 查看 sed
的版本信息
使用以下命令可以查看 sed
版本,GNU sed
会明确显示其标识:
sed --version
- 如果输出类似于以下内容,就是 GNU
sed
:sed (GNU sed) 4.8 Copyright (C) 2020 Free Software Foundation, Inc.
- 如果
sed
不支持--version
,很可能是 POSIXsed
或者较老的实现(如 BSDsed
)。
2. 测试 \s
和 \+
的行为
使用以下命令测试 sed
是否支持扩展正则语法(GNU sed
通常支持):
-
POSIX
sed
会报错,因为\s
和+
在 POSIX 中没有直接支持。
3. 检查 sed
扩展正则表达式的选项
GNU sed
支持扩展正则表达式,使用 -E
(或旧版的 -r
)选项即可启用:
echo "a b" | sed -E "s/ +/_/g"
- 如果该命令正常运行,说明你的
sed
支持扩展正则。 - 如果报错,则很可能是 POSIX 标准的
sed
。
4. \+
的行为分析
-
GNU
sed
(带扩展正则)支持\+
表示“一个或多个”。 -
如果加
-E
,+
可以直接使用,而不需要\
:echo "a b" | sed -E "s/ +/_/g"
-
如果不加
-E
,则需要反斜杠\+
来表示“一个或多个”:echo "a b" | sed "s/ \+/_/g"
5. 简单区分方法
- 如果
\s+
不工作,但\+
工作,说明你的sed
并不是严格 POSIX,而是 GNU 扩展支持的sed
。 - 兼容性高的解决方案是使用
[[:space:]]\+
或带-E
选项的写法。
总结与最佳实践
-
确定
sed
版本:sed --version
-
如果是 GNU
sed
:- 推荐用
-E
选项启用扩展正则:echo "test/myfolder # 测试 字符串" | sed -E "s/[[:space:]]+/_/g"
- 推荐用
-
如果是 POSIX 标准
sed
:- 使用
[[:space:]]\{1,\}
:echo "test/myfolder # 测试 字符串" | sed "s/[[:space:]]\{1,\}/_/g"
- 使用
-
通用推荐: 对于未知
sed
环境,使用兼容性最好的[[:space:]]\+
写法,避免\s
和+
的不确定性。
-E和-e的区别
那我是GUN的标准,刚刚用的-e 需要加\, -E就不需要\,所以参数跟大小写还有关系对吗?
是的,GNU sed
中的 -e
和 -E
参数有不同的用途,大小写确实有关系,但它们的功能完全不同。
1. -e
参数
-
作用:
-e
是用于指定脚本或表达式。 -
特点:可以同时执行多个
sed
命令。 -
用法:
sed -e 's/foo/bar/' -e 's/baz/qux/'
- 这里,
sed
会依次执行多个-e
后面的命令。 -e
是默认选项,当没有其他参数时,sed
默认会将单个字符串视为一个命令。
例子:
echo "a b" | sed -e "s/ /_/g"
输出:
a_b
注意:
-e
不会启用扩展正则,+
需要加\
(例如\+
)。 - 这里,
2. -E
参数
-
作用:启用 扩展正则表达式(Extended Regular Expressions,简称 ERE)。
-
特点:
- 不需要对
+
,?
,{}
,()
等元字符加反斜杠\
。 - 使得正则表达式更简洁。
- 不需要对
-
用法:
echo "a b" | sed -E "s/ +/_/g"
输出:
a_b
如果不加
-E
,同样的命令需要写成:echo "a b" | sed "s/ \+/_/g"
3. 大小写的关系
-
-e
和-E
是区分大小写的:-e
(小写):指定sed
命令或表达式。-E
(大写):启用扩展正则表达式。
因此,
-e
和-E
完全不一样,不能互换。
4. -r
参数与 -E
的关系
在旧版本的 GNU sed
中,-r
也用于启用扩展正则表达式。
从 GNU sed
4.2.2 版本开始,-E
是官方推荐的写法,而 -r
已经被标记为旧版本兼容。
5. 总结与区别
参数 | 功能 | 是否启用扩展正则 | 是否需要反斜杠 \ | 备注 |
---|---|---|---|---|
-e | 指定 sed 命令或表达式 | 否 | 需要 | 可同时执行多个命令 |
-E | 启用扩展正则表达式 | 是 | 不需要 | 推荐的扩展正则选项 |
-r | 启用扩展正则表达式(旧版) | 是 | 不需要 | 老版本兼容选项 |
示例对比
-
使用
-e
(不启用扩展正则):echo "a b" | sed -e "s/ \+/_/g"
输出:
a_b
-
使用
-E
(启用扩展正则):echo "a b" | sed -E "s/ +/_/g"
输出:
a_b
-
使用
-r
(旧版扩展正则):echo "a b" | sed -r "s/ +/_/g"
输出:
a_b
- 使用
-E
启用扩展正则表达式,因为这是现代 GNUsed
的标准写法。 - 在复杂脚本中,使用
-e
指定多个命令。
小结
-e
是指定sed
表达式的选项,不会启用扩展正则。-E
启用扩展正则,不需要反斜杠\
。- 确保根据实际需求选择合适的参数,避免混淆。