使用 sed 删除非字母数字字符

60
我正在尝试验证一些输入以删除一组字符。只允许字母数字字符加上加号、句点、下划线和连字符。我已经在这里http://gskinner.com/RegExr/测试了正则表达式[^\w.-],它匹配了我想要删除的内容,所以我不确定为什么sed返回相反的结果。我错过了什么吗?
我的最终目标是输入"Â10.41.89.50 "并得到"10.41.89.50"
我尝试过: echo "Â10.41.89.50 " | sed s/[^\w.-]//g 返回... echo "Â10.41.89.50 " | sed s/[\w.-]//gecho "Â10.41.89.50 " | sed s/[\w^.-]//g都返回Â10418950 我尝试了在这里找到的答案Skip/remove non-ascii character with sed,但没有任何东西被删除。

尝试在sed命令后添加-r选项,这样它就可以识别扩展正则表达式。 - Barmar
sed 不理解像 \w 这样的特殊字符类。只需使用 [a-zA-Z0-9_-] - Mark Reed
不是 -r 也不是使用 [a-zA-Z0-9_-]。 好的 echo "Â10.41.89.50 " | sed s/[a-zA-Z0-9.-]//g 返回了 Â 但是 echo "Â10.41.89.50 " | sed s/[^a-zA-Z0-9.-]//g 仍然返回了 Â10.41.89.50 - wanderingandy
6个回答

85

-c(补集)标志可能是一个选项


echo "Â10.41.89.50-._ " | tr -cd '[:alnum:]._-'

@AlexanderMills,@Herlon,虽然上面的“tr”咒语符合POSIX标准,但我手头没有MacOS来测试。 - iruvar
1
这个答案在 macOS 上可以正常工作,只是本地设置包含非英文字母在 :alnum: 字符类中(按照应有的方式)。如果你想要删除非英文字符,请尝试这样做:echo "Â10.41.89.50-._ /" | tr -cd '[a-zA-Z0-9]._-' - tjmcewan
@iruvar,我想你需要去掉那些多余的括号(类别是'[:alnum:]'而不是'[[:alnum:]]',tr 不是 sed/perl 等等)。否则,你的表达式将会允许那些非字母数字字符('[',']')通过。我刚遇到了这个问题。 - elbeardmorez
1
使用LANG=C tr -cd '...'可能是个好主意。 - Fravadona

27
您可能希望使用[:alpha:]类代替:
echo "Â10.41.89.50 " | sed "s/[[:alpha:].-]//g"

如果不起作用,您可能需要更改本地设置。

另一方面,如果您只想保留数字、连字符和句点:

echo "Â10.41.89.50 " | sed "s/[^[:digit:].-]//g"
如果您的字符串存储在一个变量中,您可以使用纯bash和参数展开来实现:

If your string is in a variable, you can use pure bash and parameter expansions for that:

$ dirty="Â10.41.89.50 "
$ clean=${dirty//[^[:digit:].-]/}
$ echo "$clean"
10.41.89.50
或者
$ dirty="Â10.41.89.50 "
$ clean=${dirty//[[:alpha:]]/}
$ echo "$clean"
10.41.89.50

你也可以查看 1_CR 的答案。


1
@dw1:不,我认为不是这样的。在第一个示例中,我们想要删除所有字母、句号和连字符,这就是该命令所做的(sed将这些符号替换为无)。最后一个示例是相同的逻辑,但使用了Bash的参数展开。 - gniourf_gniourf

15

使用以下代码仅保留字母数字和 "-" 字符:

echo "a b-1_2" | sed "s/[^[:alnum:]-]//g"

7

sed不支持Unicode字符。请改用perl

> s="Â10.41.89.50 "
> perl -pe 's/[^\w.-]+//g' <<< "$s"
10.41.89.50

@jthill: 在我的OSX上没有运行(可能是由于某些本地化设置)。 - anubhava
看起来我的OSX 10.6.8上的sed不支持Unicode,但gnu-sed应该支持Unicode。 - anubhava
1
@gorideyourbike:好的,随便使用其他答案。 - anubhava
@anubhava 不应该是语言环境问题,perl 会尊重它。我猜想苹果的 sed 版本过旧了,你运行 sed --version 看看输出是什么? - jthill
@jthill:sed --version 出现错误:sed: illegal option -- - - anubhava

2
s/[^[:alnum:]+._-]//g

删除除字母数字和".+_-"字符之外的任何内容。

echo "Â10.41.89.50 +-_" | sed s/[^[:alnum:]+._-]//g
Â10.41.89.50+-_

2
请提供一些解释。 - user3142695
@user3142695 这不是手册的替代品。这只回答了关于man sed命令的问题,没有任何技巧,也没有任何玄学。其中没有包含任何高深的知识。 - RichieHH
不,这将用空白替换输入的第一个字符 - ^ 是 sed 中字符串的开头。 - MaurGi

0
<`[[:alnum:]_.@]`

这对我来说完全有效。它保留了我为我的目的指定的所有字符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接