Contanto que os números em seu exemplo não contenham o delimitador que sed está usando (por padrão / ), o $p em seu código será interpretado como uma expressão regular (com tudo o que isso significa ).
Seu código:
search_dir='dummy'
filename='numbers.txt'
for entry in "$search_dir"/*
do
while read p;
do
sed -i '' "/$p/d" $entry
done < $filename
done
Aqui, você deseja excluir todas as linhas nos arquivos em $search_dir que contém qualquer um dos números em $filename . Se isso funciona ou não, depende de como seu sed trata -i '' . Com algumas implementações de sed , você teria que usar -i sem um argumento.
Relacionado a sed -i e portabilidade: Como posso conseguir portabilidade com sed -i (edição no local)?
É mais seguro gravar o resultado em um arquivo temporário e depois mover esse arquivo para o nome do arquivo original:
for entry in "$search_dir"/*
do
while read p;
do
sed "/$p/d" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done <"$filename"
done
Isso garante que ele funcionará independentemente de com que sed implementação você está trabalhando. Em geral, é uma má idéia tentar fazer alterações locais nos arquivos durante o teste de um script, então você pode querer comentar que mv antes de estar satisfeito com a maneira como o script funciona.
Isso ainda é um pouco inseguro como uma solução geral, já que você está realmente "usando dados como código" (os números são dados e você os usa como parte do seu script sed ). Isso significa que você pode facilmente causar um erro de sintaxe no script sed apenas inserindo um / em um dos números no arquivo de números.
Como a operação é tão simples, podemos usar grep . Isso também elimina o loop while interno:
for entry in "$search_dir"/*
do
grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done
Isso fará com que grep leia seus padrões de $filename e os aplique ao arquivo $entry . O -v significa que vamos descartar qualquer linha que contenha o padrão e -F significa grep não interpretará os números como expressões regulares, mas como sequências fixas. Com -f "$filename" , obtemos grep para ler as seqüências de caracteres de $filename .
Se houver diretórios em $search_dir , poderíamos ignorar estes:
for entry in "$search_dir"/*
do
[ ! -f "$entry" ] && continue
grep -Fv -f "$filename" "$entry" >"$entry.tmp" && mv "$entry.tmp" "$entry"
done
Outra maneira ainda mais segura de fazer sua operação é usar awk . Já que com as soluções sed e grep acima, o número é correspondido em qualquer lugar na linha, é concebível que possamos excluir as linhas erradas. Com awk , é fácil combinar apenas o segundo campo ~ -delimited nos dados:
for entry in "$search_dir"/*; do
[ ! -f "$entry" ] && continue
awk -F '~' 'NR==FNR { num[$0]; next } !($2 in num)' "$filename" "$entry" >"$entry.tmp" &&
mv "$entry.tmp" "$entry"
done
O programa awk preenche primeiro um array / hash associativo com os números como chaves e, em seguida, imprime todas as linhas do arquivo $entry cuja segunda coluna ~ -delimited não é uma chave nesse hash.