如何用sed替换包含斜杠的字符串?


147

我有一个Visual Studio项目,该项目在本地开发。代码文件必须部署到远程服务器。唯一的问题是它们包含的URL是硬编码的。

项目包含诸如?page = one之类的 URL 。为了使链接在服务器上有效,它必须为/ page / one

我已经决定在部署之前用sed替换代码文件中的所有URL,但是我只能使用斜线。

我知道这不是一个很好的解决方案,但是很简单,可以节省很多时间。我必须替换的字符串总数少于10个。必须检查的文件总数约为30个。

描述我的情况的示例如下:

我正在使用的命令:

sed -f replace.txt < a.txt > b.txt

replace.txt,其中包含所有字符串:

s/?page=one&/pageone/g
s/?page=two&/pagetwo/g
s/?page=three&/pagethree/g

a.txt:

?page=one&
?page=two&
?page=three&

运行sed命令后b.txt的内容:

pageone
pagetwo
pagethree

我想要b.txt包含什么:

/page/one
/page/two
/page/three


Answers:


274

最简单的方法是在搜索/替换行中使用其他定界符,例如:

s:?page=one&:pageone:g

您可以将任何字符用作不属于任何字符串的定界符。或者,您可以使用反斜杠将其转义:

s/\//foo/

将替换/foo。如果您不知道替换字符串中可能出现哪些字符(例如,如果它们是shell变量),则需要使用转义的反斜杠。


1
>或者,您可以使用反斜杠将其转义。举个例子可能会更有用,因为您并不总是知道字符串中有哪些字符才能选择其他内容。例如,此:echo / | sed s / \ // a / g不起作用:sed:-e表达式#1,字符5:`s'的未知选项
Max Waterman

1
那你可以加一个吗?谢谢:)我发现用双引号括起来似乎可行:echo / | sed“ s / \ // a / g”
Max Waterman

@MaxWaterman是使用sedregex命令放在双引号中时的标准操作过程。我没有在答案中使用它们,因为我没有显示整个sed命令行,而只是显示sed了OP所做的正则表达式命令字符串。如果像OP那样将其放在文件中,则不需要引号。
潜伏者

是的,足够公平(尽管也许可以提及)。这个例子有帮助。我发现有时候我需要放很多反斜线……这真的很令人困惑。例如-e“ s /'/ \\\\\\\\ // g”我认为文本是错误的,但是:“哪个将用foo替换\”-应该是“哪个/将foo替换”,不是吗?
马克斯·沃特曼

@MaxWaterman感谢您在\ vs. /上找到它。解决它。如果您sed在Shell脚本中有命令,则可能需要更多的反斜杠(每个反斜杠需要再次反斜杠)。
潜伏

105

s命令可以使用任何字符作为分隔符。s使用后会出现任何字符。我长大了使用#。像这样:

s#?page=one&#/page/one#g

5
在OS X上sed的BSD的手册页中提到了s命令:将替换字符串替换为模式空间中正则表达式的第一个实例。除反斜杠或换行符外,可以使用任何其他字符代替斜杠来分隔RE和替换字符。我敢打赌,GNU sed的手册页会说类似的话。
Tom Anderson

当前接受的答案与该答案基本相同,并且在一分钟前发布了!
汤姆·安德森

61

关于sed的一个非常有用但鲜为人知的事实是,熟悉的s/foo/bar/命令可以使用任何标点符号,而不仅是斜杠。一个常见的替代方法是s@foo@bar@,从中可以明显地看出如何解决您的问题。


天才的建议,当您要替换正斜杠时。谢谢!
mbb

9

在特殊字符前添加\:

s/\?page=one&/page\/one\//g

等等


4
我可能错过了一些东西,但是我已经尝试过了,但是似乎没有用。尝试似乎确实很明显,但是假设我是对的却确实不起作用,为什么要发布它?
codenoob

4
@codenoob(以及其他到达这里的人)-开头必须为's'。s/foo\/bar/foo_bar/可以,但是/foo\/bar/foo_bar/不会。
MynockSpit

5

在我正在开发的系统中,要用sed替换的字符串是来自用户的输入文本,该文本存储在变量中并传递给sed。

如本文前面所述,如果sed命令块中包含的字符串包含sed使用的实际分隔符-则sed会在语法错误时终止。考虑以下示例:

这有效:

$ VALUE=12345
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345

这打破了:

$ VALUE=12345/6
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
sed: -e expression #1, char 21: unknown option to `s'

在我的情况下,替换默认的分隔符不是一个可靠的解决方案,因为我不想限制用户输入sed用作分隔符的特定字符(例如“ /”)。

但是,转义在输入字符串中出现的定界符将解决该问题。考虑以下解决方案,在通过sed解析输入字符串之前,系统地转义分隔符。这种转义可以使用sed本身实现为替换,即使输入字符串包含定界符,这种替换也是安全的-这是因为输入字符串不是sed命令块的一部分:

$ VALUE=$(echo ${VALUE} | sed -e "s#/#\\\/#g")
$ echo "MyVar=%DEF_VALUE%" | sed -e s/%DEF_VALUE%/${VALUE}/g
MyVar=12345/6

我已经将其转换为各种脚本要使用的功能:

escapeForwardSlashes() {

     # Validate parameters
     if [ -z "$1" ]
     then
             echo -e "Error - no parameter specified!"
             return 1
     fi

     # Perform replacement
     echo ${1} | sed -e "s#/#\\\/#g"
     return 0
}

1
您对我的回答是,如果您要用来替换DEF_VALUE的VALUE中带有正斜杠,那么您必须用3个反斜杠将它们转义,以使sed正常工作,例如VALUE="01\\\/01\\\/2018"
alexkb

3

此行应适用于您的3个示例:

sed -r 's#\?(page)=([^&]*)&#/\1/\2#g' a.txt
  • 我曾经-r保存一些转义。
  • 对于您的一,二,三情况,该行应通用。你不必做次3次

用您的示例(a.txt)测试:

kent$  echo "?page=one&
?page=two&
?page=three&"|sed -r 's#\?(page)=([^&]*)&#/\1/\2#g'
/page/one
/page/two
/page/three


1

来自匿名的好答案。\当我尝试对HTML字符串中的引号进行转义时,解决了我的问题。

因此,如果您使用sed返回一些HTML模板(在服务器上),请使用双反斜杠而不是单反斜杠:

var htmlTemplate = "<div style=\\"color:green;\\"></div>";

1

sed小号 tream itor中,你可以使用|(管)发送标准流通过(STDIN和STDOUT明确)sed和编程改变它们的飞行,使得它在Unix哲学传统的一个方便的工具; 但也可以使用-i下面提到的参数直接编辑文件。
考虑以下几点

sed -i -e 's/few/asd/g' hello.txt

s/用于小号 ubstitute所找到的表达fewasd

少数,勇敢。


asd,勇敢。

/g代表“全局”,表示针对整行执行此操作。如果不使用/g(带有s/few/asd/,无论如何总是需要三个斜杠)并且few在同一行上出现两次,则只有第一个few变为asd

几个男人,几个女人,勇敢。


asd男人,几个女人,勇敢。

在某些情况下,这很有用,例如在行首更改特殊字符(例如,用水平制表符替换某些人用来在电子邮件线程中引用以前材料的大于号,同时在行后保留带引号的代数不等式未修改),但在您指定应替换掉的任何地方的 示例中,请few确保您拥有/g

以下两个选项(标志)组合为一个-ie

-i选项用于编辑 N将在文件上hello.txt

-e选项指示ë XPRESSION /命令来运行,在这种情况下s/

注意:使用-i -e搜索/替换很重要。如果这样做-ie,您将为每个文件创建备份,并添加字母“ e”。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.