如何用 sed 插入包含斜杠的字符串?

我有一个 VisualStudio 项目,它是在本地开发的。必须将代码文件部署到远程服务器。唯一的问题是它们包含的 URL,这些 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

返回文章页面

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

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

pageone
pagetwo
pagethree

我想让 b.txt包含的内容:

/page/one
/page/two
/page/three
238561 次浏览

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

s:?page=one&:pageone:g

您可以使用任何字符作为不属于任何字符串的分隔符。或者,你可以用一个反斜杠来避免:

s/\//foo/

foo代替 /。在不知道替换字符串中可能出现哪些字符的情况下(例如,如果它们是 shell 变量) ,可以使用转义反斜杠。

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

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

在特殊字符前加上:

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

等等。

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

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

replace.txt应该是

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

当我试图在 HTML 字符串中转义引号时,来自 Anonymous 的答案解决了我的问题。

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

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

在我正在开发的系统中,要由 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
}

您可以使用替代的正则表达式分隔符作为搜索模式,通过反向绑定它:

sed '\,{some_path},d'

对于 s 命令:

sed 's,{some_path},{other_path},'

一个更简单的替代方法是像在 这个答案上一样使用 AWK:

awk '$0="prefix"$0' file > new_file