我有以下内容:
for i in "${arr[@]}"
do
sed -r "s/$i/ANON/g" /log > /test.txt
done
但变量 i 不起作用
答案1
通过将重定向包含到循环中,您将test.txt
在每次迭代时覆盖 。您可以使用循环来创建脚本sed
并仅使用它处理文件一次:
for i in "${arr[@]}" ; do
printf 's/%s/ANON/g\n' "$i"
done | sed -r -f- /log > /test.txt
或者简单地:
printf 's/%s/ANON/g\n' "${arr[@]}" | sed -r -f- /log > /test.txt
请注意,如果数组包含 sed 中具有特殊含义的字符,它仍然可能会中断(如果数组的内容不完全在您的控制之下,甚至可能相当于命令注入漏洞)。
答案2
我假设您想arr
用单词替换数组中所有出现的任何单词ANON
。
您的代码工作得很好,但是您会覆盖循环每次迭代的输出文件,这意味着最终文件只会替换数组中的最后一个单词。
如果任何单词包含可能被解释为正则表达式字符的字符(例如和 ),*
则还存在潜在问题。[
对每个替换进行精确的字符串比较会更安全。您可以通过以下方式执行此操作awk
:
{
while (offset = index($0, str))
$0 = substr($0, 1, offset - 1) "ANON" substr($0, offset + length(str))
}
{ print }
这会将所有出现的值替换str
为字符串ANON
,即使str
包含正则表达式字符。
要从文件中读取字符串(还有一个好处是制表符分隔的字符串文件的第二列包含要替换的字符串):
BEGIN { FS = "\t" }
NR == FNR { str[$1] = $2; next }
{
for (s in str) {
sl = length(s)
while (offset = index($0, s))
$0 = substr($0, 1, offset - 1) str[s] substr($0, offset + sl)
}
}
{ print }
将制表符分隔的字符串文件指定strings
为
*password* *redacted*
My Name Not really my name
...文本文件file.txt
为
Password for the account belonging to My Name: *password*
... awk 代码会产生
Password for the account belonging to Not really my name: *redacted*
当运行为
awk -f script.awk strings file.txt