如何使用 sed 插入包含斜杠的字符串? [复制]

Posted

技术标签:

【中文标题】如何使用 sed 插入包含斜杠的字符串? [复制]【英文标题】:How to insert strings containing slashes with sed? [duplicate] 【发布时间】:2013-05-23 08:24:12 【问题描述】:

我有一个本地开发的 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

【问题讨论】:

【参考方案1】:

最简单的方法是在搜索/替换行中使用不同的分隔符,例如:

s:?page=one&:pageone:g

您可以使用不属于任一字符串的任何字符作为分隔符。或者,您可以使用反斜杠对其进行转义:

s/\//foo/

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

【讨论】:

> 或者,您可以使用反斜杠对其进行转义。这样的例子会更有用,因为您并不总是知道字符串中有哪些字符才能选择不同的东西。例如,这个:回声/| sed s/\//a/g 不起作用:sed: -e expression #1, char 5: `s' 的未知选项 那你能加一个吗?谢谢 :) 我发现用双引号括起来似乎有效:echo / | sed "s/\//a/g" @MaxWaterman 这是使用sed 时的标准操作程序,正则表达式命令放在双引号中。我没有在回答中使用它们,因为我没有显示整个 sed 命令行,而只是像 OP 所做的那样显示 sed 正则表达式命令字符串。如果你把它放在一个文件中,就像 OP 所做的那样,你不需要引号。 是的,很公平(尽管也许可以提及)。这个例子有帮助。我一直发现有时我需要输入很多很多反斜杠......这真的很混乱。例如 -e "s/'/\\\\\\\\&/g" 我认为文本是错误的,但是:“将用 foo 替换 \” - 应该是“用 foo 替换 /”,不是吗? @AbelWenning 是的,我同意。不过,我的回答并不是说冒号是最好的通用替代品。这只是表明语法允许替代方案。冒号恰好是我异想天开选择的例子。我想如果 OP 的示例有“http://”前缀,我的心血来潮可能会让我走向另一个方向。 :)【参考方案2】:

s 命令可以使用任何字符作为分隔符;使用 s 之后的任何字符。我从小就使用#。像这样:

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

【讨论】:

OS X 上 BSD sed 的手册页提到了 s 命令:用替换字符串替换模式空间中正则表达式的第一个实例.除了反斜杠或换行符之外的任何字符都可以用来代替斜杠来分隔 RE 和替换。我敢打赌,GNU sed 的手册页也有类似的内容。 目前接受的答案和这个基本一致,而且是提前一分钟发布的!【参考方案3】:

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

【讨论】:

当您想替换正斜杠时的天才建议。谢谢!【参考方案4】:

在特殊字符前加\:

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

等等

【讨论】:

我可能遗漏了一些东西,但我已经尝试过了,但它似乎不起作用。这似乎是显而易见的尝试,但假设我是对的并且它确实不起作用,为什么要发布它? @codenoob(以及其他任何到达这里的人)——开头的“s”是必需的。 s/foo\/bar/foo_bar/ 可以,但/foo\/bar/foo_bar/ 不行。【参考方案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

【讨论】:

对我来说,从你的回答中得到的收获是,如果你用来替换 DEF_VALUE 的 VALUE 中有正斜杠,那么你必须用 3 个反斜杠来转义它们,以便 sed 工作,例如VALUE="01\\\/01\\\/2018"【参考方案6】:

这一行应该适用于您的 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

【讨论】:

【参考方案7】:

请看这篇文章 http://netjunky.net/sed-replace-path-with-slash-separators/

只是使用 |而不是 /

【讨论】:

【参考方案8】:

replace.txt 应该是

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

【讨论】:

【参考方案9】:

匿名者的回答很好。 \ 解决了我尝试转义 html 字符串中的引号时的问题。

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

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

【讨论】:

【参考方案10】:

sedstream editor,因为您可以使用|(管道)通过sed 发送标准流(特别是STDIN 和STDOUT)并在fly,使它成为 Unix 哲学传统中的一个方便的工具;但也可以使用下面提到的-i 参数直接编辑文件。考虑以下

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

s/ 用于sasd 替换找到的表达式few

少数,勇敢。


asd,勇敢的人。

/g 代表“全局”,意思是对整条线都这样做。如果你去掉/g(加上s/few/asd/,无论如何总是需要三个斜杠)并且few在同一行出现两次,只有第一个few更改为asd

少数男人,少数女人,勇敢的人。


asd 男人,少数女人,勇敢的人。

这在某些情况下很有用,例如更改行首的特殊字符(例如,用水平制表符替换某些人用来引用电子邮件线程中先前材料的大于符号,而稍后留下引用的代数不等式在未触及的行中),但在您指定 anywhere few 出现的示例中,它应该被替换,请确保您有 /g

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

-i 选项用于编辑文件hello.txt 上的in 位置。

-e 选项表示要运行的 expression/命令,在本例中为 s/

注意:使用-i -e 进行搜索/替换很重要。如果您执行-ie,您会为每个附加了字母“e”的文件创建一个备份。

【讨论】:

【参考方案11】:

一个更简单的替代方法是使用 AWK,如 this answer:

awk '$0="prefix"$0' file &gt; new_file

【讨论】:

以上是关于如何使用 sed 插入包含斜杠的字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

sed命令反斜杠的转义

sed命令替换字符包含斜杠,引号的处理方法

如何将包含斜杠的变量传递给 sed

你如何 grep 一个包含斜杠的字符串?

sed:反斜杠怎么办? [复制]

使用 sed 从字符串中删除单斜杠而不是双斜杠