【问题标题】:sed search and replace strings containing / [duplicate]sed 搜索和替换包含 / [重复] 的字符串
【发布时间】:2012-05-05 19:14:05
【问题描述】:

我无法弄清楚如何使用 sed 在文本文件 /etc/myconfig 中搜索和替换包含 / 字符的字符串。

例如,在我现有的文本文件中,我有:

myparam /path/to/a argB=/path/to/B xo

我希望将其替换为:

myparam /path/to/c argB=/path/to/D xo

我尝试在 bash 中这样做:

line='myparam /path/to/a argB=/path/to/B xo'
line_new='myparam /path/to/c argB=/path/to/D xo'
sed -i 's/$line/$line_new/g' /etc/myconfig

但是什么也没发生。

尝试

grep -rn "$line" /etc/myconfig

确实返回给我'myparam /path/to/a argB=/path/to/B xo'

表达我的sed 命令以执行此搜索和替换并正确处理/ 命令的正确方法是什么? (我认为我的字符串中的/ 字符是给我带来问题的字符,因为我使用了类似的sed 命令来搜索和替换文本文件中的另一行而没有问题,并且该行没有@987654333 @ 字符。

【问题讨论】:

  • 替换和引用规则实际上是关于 bash 而不是专门针对 sed。您可能希望将 bash 添加为标签。
  • 好的。将bash 添加为标签。

标签: bash sed


【解决方案1】:

不要转义反斜杠;你会迷惑自己。在s 命令后面使用一个不同的符号,它不会出现在文本中(我在下面的示例中使用%):

line_old='myparam /path/to/a argB=/path/to/B xo'
line_new='myparam /path/to/c argB=/path/to/D xo'
sed -i "s%$line_old%$line_new%g" /etc/myconfig

另外,将整个字符串用双引号括起来;使用单引号意味着 sed 看到 $line (在原始)而不是扩展值。在单引号内,没有扩展,也没有元字符。如果您的文本几乎可以包含任何纯文本字符,请使用控制字符(例如 control-A 或 control-G)作为分隔符。

请注意,此处使用-i 反映了问题中的内容,但假设使用了GNU sed。 BSD sed(也可以在 Mac OS X 上找到)需要后缀。可以使用sed -i '' …原地替换;这不适用于 GNU sed。要在两者之间移植,请使用-i.bak;这将适用于两者 - 但会为您提供您可能想要删除的备份文件。其他 Unix 平台(例如 AIX、HP-UX、Solaris)可能有 sed 的变体,它们根本不支持 -ised 的 POSIX 规范不要求它。

【讨论】:

  • 谢谢!双引号"% 成功了。我最初尝试通过执行 \/ 来转义 / 字符,但这根本不起作用。
  • 注意,如果需要通过正则表达式指定行的范围且正则表达式中包含斜杠,可以使用sed -n '\@dir/file@,\@dir2/file2@p' where the backslash before the @`表示@是该表达式的搜索分隔符。
  • 请注意,可能需要sed -i -e
  • @PhysicalChemist:您愿意详细说明您的评论吗? -e 是可选的,除非您有多个表达式 (sed -e 's/a/b/' -b 's/xy/ZZ/g') — AFAIK。使用 sed -i -e … 将使脚本在 GNU sed 和 BSD sed 之间“可移植”,代价是让 BSD sed 创建扩展名为 -e 的备份文件(因此,如果您编辑文件 data, Mac OS X 上的备份文件将是 data-e;GNU sed 不会创建备份)。我不确定这是否是这样做的充分理由;最好使用 -i.bak 并删除备份 - 这适用于两种变体。
  • 这是唯一适合我的解决方案
【解决方案2】:

这可能对你有用:

sed -i "s|$line|$line_new|g" /etc/myconfig

您必须使用",以便插入$line$new_line。还可以使用| 或在匹配或替换字符串中找不到的任何字符作为分隔符。

【讨论】:

  • 好的。我不知道| 把戏。所以你的意思是说,只要不是在搜索或替换字符串中找到的字符,任何分隔符都可以工作?
  • 是的; s 之后的第一个字符用于将命令分成两部分;要匹配的模式和替换模式。 s/search/replace/ 使用/ 3 次;但s|search|replace|s%search%replace% 也可以。 Perl 允许匹配括号 (s{search}{replace}),但 sed 不允许(除非,如果你有 GNU sed,你可能已经激活了 Perl 模式选项)。
  • 是的,在合理范围内。 | 使用起来很方便,因为它不太可能出现在文件中。但是它是一个元字符(交替使用)所以如果你想说s/this\|that/those/ 然后使用另一个分隔符,例如@#,?% 等。还要注意这是对于搜索命令/.../ 的替换命令,使用替代分隔符在替代命令之前加上反斜杠,例如\|foo|
  • 谢谢@JonathanLeffler 我不认为 GNU sed 有一个 Perl patterns option 也许你正在考虑 ssed(超级 sed)一个 GNU sed 的分支。
  • 看来你是对的; GNU grep 有 Perl 正则表达式,但没有替换操作。这就是这些东西的难点,跟踪哪些命令有哪些非标准扩展。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2020-09-07
  • 2014-03-30
  • 2021-06-21
  • 1970-01-01
相关资源
最近更新 更多