首页 > 解决方案 > sh:逐字符传递文件并编辑它

问题描述

我知道如何使用 sh 逐个字符地传递文件:

while read -n1 char; do ... done < file.tmp

但是,在我们的循环中,我们如何在这样的字符级别上编辑、添加字符串到文件中?

例如:

while read -n1 char; do
    if [ ... ] ; then
       echo "something" here in our temp file
    fi
done < tmp.tmp

标签: bashshellloopsfilesh

解决方案


以这种方式不可能同时读取和写入同一个文件。相反,将结果打印到临时文件中并稍后重命名。

有了printf %s ...你可以打印一个没有换行符的字符。您还必须修改read它,使其不会吞下文件中的空白。

while IFS= read -d '' -N 1 char; do
    printf %s "$char"
    if [ ... ] ; then
       echo "This text and a linebreak will be inserted after $char"
    fi
done < inputfile > outputfile
mv outputfile inputfile

但是,这种方法编写起来可能非常缓慢且乏味。我会推荐一个类似sedor的工具awk

在每个之后\commandA{...},添加\commandB{...}. 所以,搜索\commandA{,等待 [...] 的结束大括号}commandA然后添加\commandB{

如果内部没有嵌套的大括号和换行符,\commandA{...}则此sed命令将执行以下操作:

sed -Ei 's#\\commandA\{[^}]*\}#&\\commandB{...}#g' file

否则,您可能想切换到perl. 这里只有转义的大括号(例如\{or \verb`{` )不被处理。

perl -p -0777 -i -e 's#\\commandA(\{(?:[^{}]++|(?-1))*+\})#$&\\commandB{...}#g' file

或者,您根本不必进行更换。相反,修改 LaTeX 命令\commandA\commandB自动包含。在你的序言中写

\let\oldcommandA\commandA
\renewcommand{\commandA}[1]{\oldcommandA{#1}\commandB{...}}

推荐阅读