通过用sed剪切最后一列而产生意外结果

时间:2019-06-17 00:01:11

标签: regex linux sed

echo '60 test' | sed -r 's/(.*)\s+[^\s]+$/\1/'

结果:

  

60次测试

最后一列未剪切。

效果很好
echo '60 home' | sed -r 's/(.*)\s+[^\s]+$/\1/'

结果:

  

60

为什么?

2 个答案:

答案 0 :(得分:6)

[^\s]+表示not backslash or s repeated 1 or more timestest包含s,而home不包含,因此后者与正则表达式匹配,而前者则不匹配。

您应该使用以下任意一种来匹配非空格:

$ echo '60 test' | sed -r 's/(.*)\s+\S+$/\1/'
60

$ echo '60 test' | sed -r 's/(.*)\s+[^[:space:]]+$/\1/'
60

正如@potong在评论中建议的那样,要删除带有sed的最后一列,您真正需要的是:

sed -E 's/\s+\S+$//'

我从-r切换到-E是因为-r仅在GNU或OSX / BSD时被GNU sed,所以通常使用BUT OSX是更好的选择/ BSD sed无法识别-E\s,因此在这种情况下,从\S更改为-r并不能使脚本更具可移植性,您必须改用它:

-E

然后完全可移植到所有POSIX sed中:

sed -E 's/[[:space:]]+[^[:space:]]+//'

否则,如果始终有2个或更多字段,则其行为将相同:

sed 's/[[:space:]]\{1,\}[^[:space:]]\{1,\}//'

答案 1 :(得分:1)

如果您只是在空格之前打印字符串的第一部分而不进行任何其他修改,则可以简单地使用cut

echo '60 test' | cut -d' ' -f1
60

在其中定义定界符(-d)和要选择的字段(-f)。 无需使用sed进行复杂的解决方案并进行一些替换操作。

使用awk,您还可以打印第一个字段:

echo '60 test' | awk '{print $1}'
60

或在perl模式下通过grep\s考虑在内

echo '60 test' | grep -oP '^.*?(?=\s)'
60