我遇到了这个命令:
ls -l <directory> \
| tail -n +2 \
| sed 's/\s\s*/ /g' \
| cut -d ' ' -f 3 \
| sort \
| uniq -c
我不确定我是否理解\s\s*
该sed
选项的目的。
我知道那\s
指的是空白。由于第二个\s
在 之前*
,这使得第二个空格匹配零次或多次。
这是否意味着sed
用一个空格替换输入流中的一个或多个连续空格?如果是,为什么不直接使用\s+
而不是\s\s*
?
答案1
\s
是编写 POSIX 表达式的 GNU 正则表达式快捷方式[[:space:]]
,它匹配任何类型的(水平或垂直)空白字符(\s
如果换行符已sed
通过其他编辑命令插入到模式空间中,则也匹配换行符)。该\s
表示法最初来自 Perl 正则表达式。
下面的一些代码[[:space:]]
虽然通常使用实际上意味着 [[:blank:]]
,仅匹配空格和制表符。
命令
sed 's/\s\s*/ /g'
用一个空格替换一个或多个连续的空白,然后重复替换,直到当前行不再有匹配项。
所以,是的,你可以用它来s/\s+/ /g
代替,但这是一个扩展(GNU) 正则表达式而不是基本表达式,因此您必须添加-E
到命令中:
sed -E 's/\s+/ /g'
现在使用非标准选项 ( -E
)和GNU 特定的正则表达式 ( \s
)。要以符合标准的方式编写命令,您必须使用
sed 's/[[:space:]][[:space:]]*/ /g'
或者
sed 's/[[:space:]]\{1,\}/ /g'
其中的含义与扩展正则表达式修饰符and (“一个或多个”)\{1,\}
相同。+
{1,}
你也可以使用
tr -s '[:blank:]' '[ *]'
它会做类似的事情,即将所有空格和制表符转换为空格并将-s
连续空格挤压()运行为单个空格。请注意,使用[:space:]
也会替换换行符(以及回车符、垂直制表符等),这可能是不需要的。
或者,您可以在该管道中完成sed
工作tail
并使用
ls -l dir | sed '1d; s/[[:space:]]\{1,\}/ /g' | cut -d ' ' -f 3 | sort | uniq -c
或者,只需使用awk
:
ls -l dir | awk 'NR > 1 { count[$3]++ } END { for (user in count) print user, count[user] }'
(使用awk
,您不必费心挤压空间)