我有大量文件需要减小大小。我发现大多数(不是全部)文件都有一个结束部分,可以在不丢失信息的情况下进行剪切:
Data 1
Data 2
something_unimportant_here END DATA
Rubbish 1
Rubbish 2
Run Code Online (Sandbox Code Playgroud)
如何通过删除包括“END DATA”在内的行和所有后续行,就地,仅更改包含该模式的文件,从而最大限度地减少对磁盘的写访问(许多,许多)来编辑文件(因此,全部)文件和慢速磁盘)。
如果可能,我想在文件中添加一个新的最后一行(我自己的结束标记),以便文件的语法保持正确——同样,仅在包含该模式的文件中。
我正在考虑使用ed,比如
echo ',s/END DATA/ ???? '\\n'q'\\n'wq' | ed "$file"
Run Code Online (Sandbox Code Playgroud)
但似乎无法管理???部分更正。
预期输出:
Data 1
Data 2
NEW END
Run Code Online (Sandbox Code Playgroud)
您应该能够通过只是截断文件到位,做到这一点,而无需编写文件的新副本一样sed -i/ perl -i/ ed/gawk -i inplace会做。与perl:
find . -name '*.txt' -type f -exec perl -ne '
BEGIN{@ARGV=map{"+<$_"}@ARGV} # open files in read+write mode in the
# while(<>) loop implied by -n
if (/END DATA/) {
seek ARGV,-length,1; # back to beginning of matching line
print ARGV "NEW END\n";
truncate ARGV, tell ARGV;
close ARGV; # skip to next file
}' {} +
Run Code Online (Sandbox Code Playgroud)
这最大限度地减少了 I/O,perl因为一旦找到匹配项就停止读取,并且 NEW END\n是它唯一写入的内容。它还写入到位,因此文件元数据(所有权、权限、acls、稀疏性...)被保留并且硬链接不会被破坏。
随着-exec {} +我们也尽量减少数量perl调用。
听起来您正在寻找的命令序列是
/END DATA/,$d
q
.a
NEW END
.
wq
Run Code Online (Sandbox Code Playgroud)
或作为单线
printf '%s\n' '/END DATA/,$d' 'q' '.a' 'NEW END' '.' 'wq'
Run Code Online (Sandbox Code Playgroud)
(您可以替换wq与,p测试。)
前任。给予
$ cat file
Data 1
Data 2
something_unimportant_here END DATA
Rubbish 1
Rubbish 2
Run Code Online (Sandbox Code Playgroud)
然后
$ printf '%s\n' '/END DATA/,$d' 'q' '.a' 'NEW END' '.' 'wq' | ed -s file
Run Code Online (Sandbox Code Playgroud)
给
$ cat file
Data 1
Data 2
NEW END
Run Code Online (Sandbox Code Playgroud)
随着GNU grep和GNU sed
grep -lZ 'END DATA' *.txt | xargs -0 sed -i -e '/END DATA/,${//i foo' -e 'd}'
Run Code Online (Sandbox Code Playgroud)
其中*.txt假设您的所有文件都在以.txt扩展名结尾的当前目录中。如果需要递归搜索文件,GNU grep也支持-r/-R选项。
/END DATA/,$ 经营范围
//i foo这里//将匹配先前使用的正则表达式,即/END DATA/并i根据需要命令将添加新的结束标记
由于i命令必须由换行符分隔,-e选项用于分隔d命令以删除范围匹配的所有行
作为替代,您也可以使用它,但一次只会将一个文件传递给sed:
grep -lZ 'END DATA' *.txt | xargs -0 -n1 sed -i -e '/END DATA/{i foo' -e 'Q}'
Run Code Online (Sandbox Code Playgroud)