xargs 命令在 ubuntu 上有效,但在 mac 上无效

xargs 命令在 ubuntu 上有效,但在 mac 上无效

我有以下代码行,用于将项目中的个人日期变量更新为今天的当前日期。此行在 Ubuntu 终端中有效,但 Mac 终端似乎远远落后。不幸的是,我从某个网站复制了此代码片段,因此我不确定它究竟是如何工作的。有什么建议吗?

grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" * |
    grep -v .git | xargs -i@ sed -i "s/\[DATE\]/${today}/g" @

答案1

它是如何工作的

  1. 生成文件名列表:

    grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" *
    

    以递归方式 (-r) 搜索文件并列出 (-l) 文件内容与正则表达式 '[DATE]' 不区分大小写 (-i) 匹配的文件名称(表示文件包含 8 个字符“AaDdEeTt”中的任意一个);排除名称 revar.sh 和 README.md,并且

  2. 从列表中删除所有包含字符“git”的文件名(因此文件名“agitator”将被删除):

    grep -v .git
    
  3. 一次处理一个文件,将特定的“sed”脚本应用于文件。在现代符号中(POSIX - 和 MacOS X,以及 Linux、AIX、HP-UX、Solaris 等):

    xargs -I@ sed -i "s/\[DATE\]/${today}/g" @
    

    “sed”的“-i”选项表示在处理后覆盖输入文件。这是 GNU 和 BSD 对“sed”的扩展,POSIX 标准中未指定。

难以置信的是什么

这个剧本可以在多个层面受到批评。

  • 第一个搜索字符串不正确;它应该在括号前有反斜杠;大多数文件至少包含一个字母“dateDATE”。
  • 第二个 grep 大概是要删除“.git”目录下的所有内容,需要修复。
  • 与第一个“grep”不同,“sed”命令在查找“[DATE]”时不区分大小写。

如何修复

因此,两种选择之一都是有意义的。

任何一个:

grep -ilr --exclude=revar.sh --exclude=README.md "\[DATE\]" * |
grep -v '\.git/' |
xargs sed -i "s/\[[Dd][Aa][Tt][Ee]\]/${today}/g"

或者:

grep -lr --exclude=revar.sh --exclude=README.md "\[DATE\]" * |
grep -v '\.git/' |
xargs sed -i "s/\[DATE\]/${today}/g"

正如 Donal Fellows 所指出的,在这种情况下没有必要使用‘xargs’的‘-i’或‘-I’选项。

即使修好了还有用吗?

这让我很困惑它到底有什么用。第一天,所有出现的 '[DATE]' 都映射到 '2010-04-17';第二天会发生什么?如何在提交到 git 存储库之前取消日期映射?

不过,至少你现在知道它的作用是什么以及它是如何做到的。

答案2

BSDxargs没有-i,而且该选项在 GNU xargs 中已被弃用(本指南是什么时候写的?1995 年?)。请改用-I

答案3

当执行替换的位置在字符串末尾时,永远不需要-i选项;文件名无论如何都会放在那里。而且 BSD (OSX 提供的)也不支持该选项。所以试试这个:xargsxargs

grep -ilr --exclude=revar.sh --exclude=README.md "[DATE]" * |
    grep -v .git | xargs sed -i "s/\[DATE\]/${today}/g"

答案4

使用 Bash 参数扩展您还可以几乎自动地避免 sed 格式问题:

# some basic Bash parameter expansion examples to play with
var='ddd/abc/ddd'
var="$(date)"
var=$'\\\n'

echo abc | sed 's/b/'"${var}"'/g'
echo abc | sed 's/b/'"${var//\//\\/}"'/g'

相关内容