![将“expand”命令应用到文件,如 sed -i](https://linux22.com/image/1496323/%E5%B0%86%E2%80%9Cexpand%E2%80%9D%E5%91%BD%E4%BB%A4%E5%BA%94%E7%94%A8%E5%88%B0%E6%96%87%E4%BB%B6%EF%BC%8C%E5%A6%82%20sed%20-i.png)
该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”用户简化了这一过程。