175

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

该项目包含 URL,例如?page=one. 要使链接在服务器上有效,它必须是/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&

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

pageone
pagetwo
pagethree

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

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

11 回答 11

313

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

s:?page=one&:pageone:g

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

s/\//foo/

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

于 2013-05-28T11:24:22.773 回答
119

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

s#?page=one&#/page/one#g
于 2013-05-28T11:25:16.290 回答
71

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

于 2013-05-28T11:25:44.980 回答
12

在特殊字符前添加 \:

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

等等

于 2013-05-28T11:25:23.483 回答
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
}
于 2017-05-07T14:55:55.763 回答
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
于 2013-05-28T11:27:31.253 回答
2

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

只是使用 | 代替 /

于 2020-07-30T14:13:25.780 回答
1

replace.txt应该

s/?page=/\/page\//g
s/&//g
于 2013-05-28T11:33:25.007 回答
1

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

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

var htmlTemplate = "<div style=\\"color:green;\\"></div>";
于 2014-05-17T19:34:29.553 回答
0

seds tream ed itor,因为您可以使用|(pipe) 发送标准流(特别是 STDIN 和 STDOUT)sed并以编程方式即时更改它们,使其成为 Unix 哲学传统中的便捷工具;-i但也可以使用下面提到的参数直接编辑文件。
考虑以下内容

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

s/用于将找到的表达式替换fewasd

少数,勇敢。


asd,勇敢的人。

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

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


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

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

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

-i选项用于就地编辑文件hello.txt

-eoption 表示要运行的表达式/命令,在这种情况下为s/.

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

于 2017-11-23T09:04:49.437 回答
0

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

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

于 2019-01-15T18:39:07.230 回答