【问题标题】:Replace string with spaces recursively using sed on Mac在 Mac 上使用 sed 递归地用空格替换字符串
【发布时间】:2013-11-02 14:17:32
【问题描述】:

在尝试解决此问题一小时后宣布破产。问题来了:

我有一个包含 15,000 个文件的文件夹 (Magento)。我想将所有版权日期从 2013 年更改为 2012 年,这样我就可以获得版本之间的合法差异。我正在尝试使用 sed,基于此示例:https://stackoverflow.com/a/1583282

此命令有效:

cd path/to/project
find . -type f -print0 | xargs -0 sed -i '' 's/2013/2012/g'

除了,我显然不能相信 2013 年仅适用于日期。 Magento 的 DocBlocks 中的完整字符串是:

* @copyright   Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)

我正在尝试重写 sed 表达式以使用“(c) 2013 Magento”作为字符串,但出现错误:

sed: RE error: illegal byte sequence

显然,有些东西需要转义,但我找不到任何适用的例子。无论如何,我都不是 bash 向导。

这部分表达式的正确格式是什么?

's/(c) 2013 Magento/(c) 2012 Magento/g'

【问题讨论】:

标签: bash magento sed


【解决方案1】:

显然,有些东西需要转义,但我找不到任何适用的例子。无论如何,我都不是 bash 向导

无论你是什么巫师,你都已经将 Stack Overflow 小矮人派到了幽暗密林。您的问题不是命令转义。以下将运行良好。

find . -type f -print0 | xargs -0 sed -i '' 's/2013 Magento Inc./2012 Magento Inc./g'

通过在一个空目录中运行它来测试它。

$ mkdir tmp-gandalf
$ cd tmp-gandalf
$ find . -type f -print0 | xargs -0 sed -i '' 's/2013 Magento Inc./2012 Magento Inc./g'

如果你遇到了 shell 转义问题,你的系统会在这里抱怨它。

这就是问题所在。命令的第一部分查找所有要操作的文件

find . -type f -print0

使用-type f 查找所有文件。包括非文本文件。 sed 命令不喜欢非文本文件。试试这样的

sed -i '' 's/2013 Magento Inc./2012 Magento Inc./g' /path/to/some.gif
find . -name '*.php' -o -name '*.xml' -o -name '*.phtml'

/path/to/some.gif 是一个二进制文件。你会看到你的sed: RE error: illegal byte sequence 错误。那是sed 说“wtf,我不像爆破机那样笨拙或随意。我来自一个更加文明的时代,一切都是 ASCII”。

这个Stack Overflow 问题有一个稍微复杂的解决方法(调整LANG 属性)。我不知道这是否是个好主意。

我个人的做法是限制您的find,以便只包含具有特定扩展名的文件。您可以使用-o 选项指定多个名称模式。所以像这样的

//NOTE: each -o needs its own -print0
find . -name '*.php' -print0 -o -name '*.xml' -print0 -o -name '*.phtml' -print0 | xargs -0 sed -i '' 's/2013 Magento Inc./2012 Magento Inc./g'

将搜索 .php.xml.phtml 文件。您可以将js 文件与另一个-o -name '*.js' 添加。 Magento 代码库中应该只有少数文件类型带有版权声明。

【讨论】:

  • 二进制文件问题非常有意义,感谢您使用正确的 LOTR/SW 措辞,所以我会理解的。使用多个名称参数运行您的最终命令确实会执行,但不会将替换写入文件中。我知道这就是“sed -i”参数的意思,但它似乎没有那种效果。我还尝试将 {} 添加到末尾(我认为这会将文件列表从“find”命令传递到“sed”,但这没有效果。有什么想法吗?
  • 我很确定您需要添加 -e 以便您的命令看起来像这样 find 。 -name "*.xml" -type f -exec sed -i -e 's/RegEx/Replacement/g' {} \;
【解决方案2】:

试试这个 sed:

 sed 's/\(©\) 2013 \(Magento\)/\1 2012 \2/g'

【讨论】:

  • 你可以试试:sed 's/2013.*\(Magento\)/2012 \1/g'
  • 请问您的 sed 版本是什么?由于sed 's/2013.*\(Magento\)/2012 \1/g' 没有任何Unicode 字符
【解决方案3】:

找到 /full/path/to/magento -type f -print0 | xargs -0 sed -i '' 's/(c) 2013 Magento/(c) 2012 Magento/g'

但是:

grep -lir -e '2013 Magento' /full/path/to/magento /full/path/to/magento/app/code/core/Enterprise/Enterprise/etc/config.xml /full/path/to/magento/app/code/core/Mage/Page/etc/config.xml /full/path/to/magento/app/locale/en_US/Mage_Page.csv /full/path/to/magento/errors/default/page.phtml /full/path/to/magento/errors/enterprise/page.phtml /full/path/to/magento/downloader/template/footer.phtml /full/path/to/magento/downloader/template/install/footer.phtml

这些文件仍会在文件中放置“© 2013 Magento”

这应该可行:

找到 /full/path/to/magento -type f -print0 | xargs -0 sed -i '' 's/2013 Magento/2012 Magento/g'

【讨论】:

  • 不。收到此错误:sed: 1: "./.!14184!.DS_Store": invalid command code .
  • 从这个命令: find 。 -type f -print0 | xargs -0 sed -i 's/2013 Magento/2012 Magento/g'
  • 对不起..“在 Mac 上”编辑了我的答案。
【解决方案4】:

简单地转义括号似乎对我有用:

$ sed 's/\(c\) 2013 Magento/\(c\) 2012 Magento/g' <<< "@copyright   Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)"
@copyright   Copyright (c) 2013 Magento Inc. (http://www.magentocommerce.com)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 2014-09-16
    • 1970-01-01
    • 2014-09-05
    • 2020-09-12
    • 2010-12-07
    相关资源
    最近更新 更多