【问题标题】:Using sed with regex to replace text on OSX and Linux使用 sed 和正则表达式替换 OSX 和 Linux 上的文本
【发布时间】:2017-01-22 05:03:23
【问题描述】:

我正在尝试使用正则表达式将文件中的一些字符串替换为sed。更复杂的是,这是在 Makefile 脚本中完成的,该脚本需要同时在 osxlinux 上工作。

具体来说,在file.tex内我要替换

\subimport{chapters/}{xxx}

\subimport{chapters/}{xxx-yyy}

xxxyyy 只是示例文本。)

注意,xxx 可以包含任何字母、数字和_(下划线),但实际上正则表达式可以简单地匹配括号内的任何内容。有时\subimport...之前的行首会有一些空格。

要搜索的字符串的设计需要大量转义(当使用正则表达式搜索时),我猜其中某处是我的错误。

这是我迄今为止尝试过的:

sed -i'.bak' -e 's/\\subimport\{chapters\/\}\{xxx\}/\\subimport\{chapters\/\}\{xxx-yyy\}/g' file.tex
# the -i'.bak' is required so SED works on OSX and Linux
rm -f file.tex.bak # because of this, we have to delete the .bak files after

当我构建包含此脚本的 Makefile 时,这会导致错误 RE error: invalid repetition count(s)

我认为我的部分问题是sed-E 选项在osx 版本的sed 中不可用。事实证明,当使用 -E 选项时,应该转义的东西更少(请参阅我的问题中的 cmets)。

【问题讨论】:

  • -E 选项在 OS X 中可用,这将是 Linux 上的 -r 选项。
  • @l'L'l 当我使用-E 选项时,我收到not defined in the RE 错误。即使它对我有用,我也无法设置 POSIX 选项,因为 OSX/BSD 以一种方式进行,而 GNU 以另一种方式进行。
  • 那是因为你正在转义捕获组,使用-E时不需要这样做(例如,而不是\( ... \),只需使用( ... )
  • 如果您在Makefile 中使用sed 命令并希望根据操作系统使用不同的命令,您可以始终使用类似的条件:UNAME := $(shell uname); ifeq ($(UNAME), Linux)...
  • 你并没有真正改变你的问题——只是更正它,这就是编辑功能的用途:) 也许只是假设你认为它在 OS X 上不可用,但要找出它确实存在。

标签: regex linux macos sed makefile


【解决方案1】:

POSIX-ly:

sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#'
  • # 用作seds 的参数分隔符(替换)

  • \(\\subimport{chapters/}{[[:alnum:]_]\+\) 是捕获的组,包含直到最后一个 } 所需的所有内容,前面是一个或多个字母、数字和下划线

  • 在替换中,第一个捕获的组后面是所需的字符串,由}关闭

示例:

$ sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#' <<<'\subimport{chapters/}{foobar9}'
\subimport{chapters/}{foobar9-yyy}

$ sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#' <<<'\subimport{chapters/}{spamegg923}'
\subimport{chapters/}{spamegg923-yyy}

【讨论】:

  • 如果我只想编辑文件file.tex,POSIX-ly,我该怎么做?
  • @ScottWilton Do:sed -i.bak 's#...' file.tex,原文件将备份为file.tex.bak。没有备份:sed -i '' 's#...' file.tex
  • 这对我不起作用。在 makefile 和以下简单测试中(在 osx 上的 bash 中):echo '\subimport{chapters/}{01_general}' | sed 's#^\(\\subimport{chapters/}{[[:alnum:]_]\+\)}$#\1-yyy}#''。这不会产生任何变化(\subimport{chapters/}{01_general})。你上面的例子也不适合我。
  • 好的,所以sed -i.bak -E 's#^(\\subimport{chapters/}{[[:alnum:]_]+)}$#\1-yyy}#' file.tex 至少可以在我的机器上运行。唯一的问题是\subimport ... 前面有时会有空格。我尝试在表达式中添加\s*,但没有成功。
  • @ScottWilton \s 不是 POSIX。做:^\([[:blank:]]*\\subimport...
【解决方案2】:

这是最终为我工作的版本。

sed -i.bak -E 's#^([[:blank:]]*\\subimport{chapters/}{[[:alnum:]_]+)}$#\1-yyy}#' file.tex
rm -f file.tex.bak

非常感谢@heemayl。他们的答案写得更好,只需进行一些调整即可获得适合我的版本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 2015-04-01
    • 2018-01-07
    • 2021-12-31
    • 2018-08-22
    • 2018-04-23
    相关资源
    最近更新 更多