我正在尝试>>>
用文件中的“”替换
cat table_files.md | egrep ">>>$"
\>>>
\>>>
\>>>
\>>>
\>>>
\>>>
\>>>
\>>>
\>>>
将其替换为 sed
cat table_files.md | sed "s\>>>$\\g" > table_files.md
不幸的是,我所有的数据都消失了,它反馈给我一个空白文件。我检查这应该使用-i
就地选项来完成。
怎么会这样,数据还能恢复吗?
答案1
文件被覆盖/截断的原因是它是您的壳它解释重定向,并在任何命令运行之前执行此解释。 shell 工作的一个重要部分是处理在各种事物之间连接标准输入和标准输出的管道。您发出了如下命令行:
$ command1 < somefile | command2 > somefile
甚至在command2
运行之前,shell 就已经解释了重定向,该重定向会将命令的输出定向到文件,从而截断该文件。文件被截断后,没有可供command1
读取的输入,因此它退出,关闭到 的管道command2
,该管道也退出,而没有发出任何要重定向到文件的数据。
看来你有两个问题......
1. 我可以恢复我覆盖的文件吗?
可能不会。如果可以的话,可以通过恢复备份来完成。用其他数据覆盖文件通常会消除该文件的旧版本。
2. 替换文件中数据的最佳方法是什么?
正如您所猜测的,执行此操作的最佳方法是sed将使用-i
(就地)选项。请记住,这不是真的就地编辑。该-i
选项使 sed 读取其所有输入,对其进行修改并将其存储在临时存储中,完成后将所有内容从临时存储移回原始文件。
在 BSD sed(包括 macOS)中:
sed -i '' 's:>>>$::' $filename
但在 GNU sed(大多数 Linux 发行版)中,未指定的 optarg to-i
被认为是 null:
sed -i -e 's:>>>$::' $filename
这会删除>>>
行尾的 。如果要从行内删除字符串,请修改正则表达式,使其不锚定到行尾 ( $
),并添加标志g
以使其应用于每行的多个字符串:
sed -i '' 's:>>>::g' $filename
请注意,不同的操作系统以不同的方式运行 sed。当您编写想要共享的工具时,请务必记住,并非每个人都运行与您相同的操作系统。便携性很重要。为了使事情可移植,您可能必须简化脚本,以便它们使用您想要支持的所有平台上可用的功能的“最低公分母”。因此:
tmpfile=$(mktemp /tmp/$$XXXX)
sed -e 's:>>>$::' $filename > $tmpfile &&
mv $tmpfile "$filename"