理解 sed 命令: sed 's/\s\s*/ /g'

Mik*_*keB 3 sed regular-expression

我遇到了这个命令:

ls -l <directory> | tail -n +2 | sed 's/\s\s*/ /g' | cut -d ' ' -f 3 | sort | uniq -c  
Run Code Online (Sandbox Code Playgroud)

我不是100%肯定,如果我理解的目的\s\s*sed选项。

我知道这\s是指一个空格。由于第二个\s*,这使得第二个空格匹配零次或多次。

这是否意味着sed用单个空格替换输入流中的一个或多个连续空格?如果是,为什么不直接使用\s+代替\s\s*

Kus*_*nda 10

\s是编写 POSIX 表达式的 GNU 正则表达式快捷方式[[:blank:]],它匹配空格或制表符(\s如果换行符已sed通过其他编辑命令插入到模式空间中,则也匹配换行符)。该\s符号最初来自 Perl 正则表达式,但在 Perl 正则表达式中,它的工作方式类似于[[:space:]]POSIX 表达式,匹配更广泛的产生空格的字符数组。

命令

sed 's/\s\s*/ /g'
Run Code Online (Sandbox Code Playgroud)

用一个空格替换一个或多个连续的空格/制表符,然后重复替换,直到在当前行上不再有匹配项。

所以,是的,您可以s/\s+/g改用,但这是扩展(GNU) 正则表达式而不是基本正则表达式,因此您必须添加-E到命令中:

sed -E 's/\s+/ /g'
Run Code Online (Sandbox Code Playgroud)

这现在使用非标准选项 ( -E)GNU 特定的正则表达式 ( \s)。要以符合标准的方式编写命令,您必须使用

sed 's/[[:blank:]][[:blank:]]*/ /g'
Run Code Online (Sandbox Code Playgroud)

或者

sed 's/[[:blank:]]\{1,\}/ /g'
Run Code Online (Sandbox Code Playgroud)

where\{1,\}表示与扩展正则表达式修饰符+{1,}(“一个或多个”)相同。

你也可以使用

tr -s '[:blank:]' ' '
Run Code Online (Sandbox Code Playgroud)

这会做同样的事情,即将所有空格和制表符转换为空格并将-s连续空格挤压 ( ) 运行到单个空格。

或者,您可以在该管道中sed完成工作tail,并使用

ls -l dir | sed '1d; s/[[:blank:]]\{1,\}/ /g' | cut -d ' ' -f 3 | sort | uniq -c
Run Code Online (Sandbox Code Playgroud)

或者,只需使用awk

ls -l dir | awk 'NR > 1 { count[$3]++ } END { for (user in count) print user, count[user] }'
Run Code Online (Sandbox Code Playgroud)

(使用awk,您不必费心挤压空格)

  • @mazunki `+` 修饰符是 POSIX 扩展正则表达式中的标准。但是,POSIX 标准的`sed` 目前只为_basic_ POSIX 正则表达式定义,不支持`+`。因此,您可以在 `sed` 中启用 `+`(这是一个标准修饰符)的使用,但前提是您使用非标准选项。 (3认同)