将“expand”命令应用到文件,如 sed -i

将“expand”命令应用到文件,如 sed -i

expand命令不具有相当于

sed -i <file>

expand实际上确实有一个-i选择 - 但这意味着

仅在空格后

是否有一个sed充满expand活力的二人组合可以达到同样的目的?

答案1

GNU 实用程序 expand 不提供 sed 提供的“就地”更新。重现相同结果相当简单,尽管命令可能略长。

在任意文件系统上同时解析和更新文件是不可能的,否则可能会造成损坏,出于这个原因和其他原因,sed 实际上不会这样做,尽管它从用户那里抽象了这一点。sed 所做的(您可以自己重现)是,它将对目标文件的操作输出保存在临时文件中,然后删除原始副本并将临时文件重命名为原始文件。

有很多种方法可以做到这一点,这里是其中一种——名为 orig.txt 的文件是被“扩展”的文件:

tmp=`mktemp` && expand orig.txt > "$tmp" && mv "$tmp" orig.txt

如果您从未使用文件名以外的任何参数来扩展,则一个名为的简单函数expand可以将整个临时文件隐藏到原始文件交换中,并重现该sed行为 - 此实现将采用路径/文件名的单个参数

expand() {
  [[ "$#" -ne "1" ]] && { echo "A single argument must be provided"; exit 1; }
  tmp=`mktemp` && expand "$1" > "$tmp" && mv "$tmp" "$1"
}

稍加修改,我们就可以expand通过支持参数来重新创建所有功能。获取最后一个参数时有一个小技巧,这样我们就知道目标文件的文件名,最终可以用 的输出覆盖它expand。最后一个参数引用为${@ -1}

expand() {
      [[ "$#" -lt "1" ]] && { echo "At least a file name argument must be provided"; exit 1; }
      # Here we capture the last argument which is the object file name
      fname="${@: -1}"
      # The upcoming call to expand passes on all arguments including the file name
      tmp=`mktemp` && expand "$@" > "$tmp" && mv "$tmp" "$fname"
    }

我没有测试这段代码,所以如果我没有发现语法错误,我深感抱歉。

这些函数之一,或者它们的某个版本,应该放入.bashrc或放入一个等效文件中,该文件在您创建新的 shell 时提供,以便随时可用。

如果您希望能够指定文件是否“就地”更新或将更新发送到 stdout,则可以根据附加参数(不会传递给 expand,但会改变我们调用 expand 的方式)修改此函数模板。我不确定您是否正在寻找它,但我认为如果您正在寻找的话,您现在拥有执行此操作所需的所有信息。

或者为了更多乐趣,下载 GNU coreutils源代码sed 源代码,查看 sed 如何处理它,并将该代码迁移到新改进的 expand 版本中。将该更改发送回维护者,您可能已经为所有未来的“expand”用户简化了这一过程。

相关内容