如何从文本文件中删除包含特定字符串的所有行
技术背景
在系统运维和文件处理过程中,经常需要从文本文件中删除包含特定字符串的行。这在清理日志文件、处理配置文件等场景中非常常见。不同的工具和方法可以实现这一目的,下面将详细介绍各种实现方式。
实现步骤
使用 sed
1
| sed '/pattern to match/d' ./infile
|
1
| sed -i '/pattern to match/d' ./infile
|
- 直接修改文件(BSD sed,如 Mac OS X 和 FreeBSD):
1
| sed -i '' '/pattern to match/d' ./infile
|
- 直接修改文件并创建备份(BSD 和 GNU sed):
1
| sed -i.bak '/pattern to match/d' ./infile
|
使用 AWK
1
| awk '!/pattern/' file > temp && mv temp file
|
使用 Ruby (1.9+)
1
| ruby -i.bak -ne 'print if not /test/' file
|
使用 Perl
1
| perl -ni.bak -e "print unless /pattern/" file
|
使用 Shell (bash 3.2 及以后)
1 2 3 4 5
| while read -r line do [[ ! $line =~ pattern ]] && echo "$line" done <file > o mv o file
|
使用 GNU grep
1
| grep -v "pattern" file > temp && mv temp file
|
使用 ex
使用 vim
使用 ed
1
| printf "%s\n" "g/pattern/d" w | ed -s filename
|
或者使用 heredoc:
1 2 3 4
| ed -s filename <<EOF g/pattern/d w EOF
|
核心代码
以下是一些核心代码示例:
sed 示例
1 2
| sed -i '/pattern/d' filename
|
grep 示例
1 2 3 4
| grep -v 'pattern' filename
echo "$(grep -v "pattern" filename)" >filename
|
Perl 示例
1 2
| perl -i.bk -nle'/regexp/||print' file1 file2 file3
|
最佳实践
- 性能方面:根据测试,在处理约 345000 行的文件时,
grep
方法比 sed
方法快约 15 倍。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt
time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt
time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )
|
- 精确匹配:如果需要精确匹配字符串,可以使用
grep
的 -w
标志。例如,要删除包含数字 11 的行,但保留包含 111 的行:
常见问题
- sed 兼容性问题:
sed
的 -i
选项在不同系统(如 GNU sed 和 BSD sed)中用法不同。GNU sed 可以直接使用 -i
进行原地修改,而 BSD sed 需要 -i ''
。 - 变量替换问题:在使用
sed
进行变量替换时,需要使用双引号。例如:
1
| sed -i '' "/$pattern/d" $file
|
- 字符串转正则问题:如果要将任意字符串转换为正则表达式,可以使用以下方法:
1 2
| re=$(sed 's/\([\[({.*+^$?]\)/\\\1/g' <<< "$STRING") sed "/$re/d" FILE
|