我的服务器上的文件已损坏。我想从包含 13000 个字符串的所有 PHP 文件中删除它。
该字符串看起来像:
?php if(!isset($GLOBALS["\x61\156\x75\156\x61"])) { $ua=strtolower($_SERVER[ ... $qhroczocgv=$qjhvvbyvyv; $qhroczocgv=(729-608); $boxknervrr=$qhroczocgv-1; ?>
为了简洁起见插入了省略号。
当我使用 搜索字符串时grep
,我得到一个
grep: 无效的反向引用”尽管转义了 \![]$
如何首先找到包含整个字符串的所有文件,然后如何从每个文件中删除文本?
答案1
假设您有良好的编码约定,只需删除大于特定大小的任何行:
shopt -s extglob nullglob
sed -i.bak -r '/.{10000}/d' **/*.php
对于@通配符:
find . -name '*.php' -print0 | while IFS= read -rd "" file; do
before=$(wc -l < "$file")
after=$(sed -r '/.{10000}/d' "$file" | wc -l)
case $(( diff = before - after )) in
0) :;; # no-op
*) echo "will remove $diff lines from $file";;
esac
done
答案2
尝试使用fgrep
or ,等效地,grep -F
.这会将模式解释为固定字符串。
您还可以将该单个字符串放入文件中(单独)并用于grep -f filename
指定文件。不过,您仍然需要该-F
标志。
请参阅man grep
其他选项;有几个可能有用的。
有关删除与给定模式匹配的行的各种方法,请参见https://stackoverflow.com/a/5413132/5419599。
综合起来,一种方法是:
- 将该行文本单独放入一个文件中。称之为“模式文件”。
- 跑步
grep -lrFf patternfile . > filelist
- 编辑
filelist
以删除该行./patternfile
- 跑步
for i in $(cat filelist) ; do grep -vf patternfile $i > temp && chmod --reference=$i temp && mv temp $i ; done
步骤2中,grep选项为:-l
列出匹配的文件;-r
递归到子目录;-F
使用固定字符串作为模式进行匹配;-f
使用文件patternfile
作为匹配模式;然后当然> filelist
要创建一个包含匹配文件列表的文件。
在第4步中,grep
只需使用-v
标志来打印非匹配行,然后chmod
确保不会出现权限问题,并将mv
文件放回原位。
可能有更好的方法,但我认为这就足够了。
编辑:如果您以 root 身份运行它,并且并非所有这些文件都归 root 所有,请执行步骤 4 的以下修订版本:
for i in $(cat filelist) ; do grep -vf patternfile $i > temp && chown --reference=$i temp && chmod --reference=$i temp && mv temp $i ; done
如果您是所有文件的所有者,则最初的步骤 4 就可以。
答案3
假设该字符串在您的文件中相当独特,您可以使用一些正则表达式来查找该字符串的一些值得注意的部分,并使用 afind
和 ased replace
将其切换出来
find . -name "*.php" -exec sed -i 's/?php.*strtolower.*qhroczocgv.*boxknervrr.*-1; ?>//g' {} \;
但这会在其位置留下一个空行。
您知道该字符串是否是一行中唯一存在的字符串吗?如果是这样,你可以尝试用以下方法简化它:
find . -name "*.php" -exec sed -i 's/?php.*strtolower.*qhroczocgv.*boxknervrr.*-1; ?>//g' {} \;
它将查找包含 php、任意数量的其他字符、后跟 strtolower 任意数量的其他字符、后跟 qhroczocgv 后跟任意数量的其他字符、后跟 boxknervrr 后跟任意数量的其他字符的字符串,然后删除整行。
同样在该find
部分中,.
当然代表当前目录,但您可以将其切换为您选择的目录。