Linux Sed:用一个下划线替换一系列点

Linux Sed:用一个下划线替换一系列点,linux,bash,command-line,sed,Linux,Bash,Command Line,Sed,我想用sed在Bash中做一些简单的字符串替换。我是Ubuntu 10.10 只要看下面的代码,它是不言自明的: name="A%20Google.." echo $name|sed 's/\%20/_/'|sed 's/\.+/_/' 我想得到A_谷歌但我得到A_谷歌.. sed的/\.+/\/'部分显然是错误的 顺便说一句,sed的/\%20/\/'和sed的/%20/\/'都可以工作。哪个更好?sed命令不理解+,因此您必须手动展开它: sed 's/\.\.*/_/' 或者告诉se

我想用sed在Bash中做一些简单的字符串替换。我是Ubuntu 10.10

只要看下面的代码,它是不言自明的:


name="A%20Google.."
echo $name|sed 's/\%20/_/'|sed 's/\.+/_/'
我想得到
A_谷歌
但我得到
A_谷歌..

sed的/\.+/\/'部分显然是错误的


顺便说一句,
sed的/\%20/\/'
sed的/%20/\/'
都可以工作。哪个更好?

sed命令不理解
+
,因此您必须手动展开它:

sed 's/\.\.*/_/'
或者告诉sed您想使用扩展正则表达式:

sed -r 's/\.+/_/' # GNU
sed -E 's/\.+/_/' # OSX

哪个开关,
-r
-E
,取决于您的
sed
,它甚至可能不支持扩展正则表达式,因此便携式解决方案是使用
\.\.*
代替
\.+
。但是,既然你是在Linux上,你应该有GNU
sed
,所以
sed-r
应该可以做到这一点。

sed
讲POSIX基本正则表达式,它不包括作为元字符的
+
。可移植地重写以使用
*

sed 's/\.\.*/_/'
或者,如果您只关心Linux,您可以使用各种GNU ISM:

sed -r 's/\.\.*/_/'    # turn on POSIX EREs (use -E instead of -r on OS X)
sed 's/\.\+/_/'        # GNU regexes invert behavior when backslash added/removed
最后一个示例回答了您的另一个问题:一个按原样使用的文字在反斜杠时可能具有特殊意义,即使此时反斜杠时
%
没有特殊意义,未来校对意味着不假设
\%
是安全的

附加说明:在那里的管道中不需要两个单独的
sed
命令

echo $name | sed -e 's/\%20/_/' -e 's/\.+/_/'

(另外,您是每行只需要执行一次,还是所有出现的情况都需要执行一次?您可能需要使用
/g
修饰符。)

直觉:试试
's/\.\.*/'
。您的sed可能无法正确处理
+
。@Beta:Hi我想知道
sed的/\.*/'
为什么不能工作。谢谢。因为
\.*
将匹配任意数量的点,包括零,例如“A_Google..”开头的无点。我不太理解你的
\%
部分。你的意思是说,
\%
没有特殊意义,但将来可能会改变?因此,
%
是一个更好的解决方案。我不知道什么时候应该添加反斜杠,什么时候不应该添加反斜杠。你必须知道使用的是什么正则表达式语言,
%
\%
的对比是复杂的,因为POSIX的GNU解释,BRE中不存在的ERE元字符可以反斜杠以获得ERE的含义(因此,
\+
在大多数版本的
sed
中表示文字
+
,但在GNU
sed
中表示前面的一个或多个文字).不幸的是,regex的前景是一场隐藏着地雷的噩梦,在可预见的未来仍将如此;你别无选择,只能确切地知道一个程序使用什么regex引擎以及该引擎的怪癖是什么。