Eu tenho uma matriz de valores v
que quero remover do arquivo f
. f
é delimitado por NUL. Como eu prossigo? Tentei usar sd
, mas não funcionou .
Exemplo:
Eu tenho este arquivo:
# cat -v $attic
^@this is 1.
this is 2.
this is 3.
^@hi
^@blue boy
E esta variável $i
:
# cat -v <<<"$i"
this is 1.
this is 2.
this is 3.
Eu quero um comando que remova $i
desse arquivo, resultando em:
^@hi
^@blue boy
Eu tentei FROM="$i" perl -pi -e 's/\0\Q$ENV{FROM}\E//g' "$attic"
, mas não funciona se $i
for multilinha. Eu tentei, FROM="$i" perl -pi0 -e 's/\0\Q$ENV{FROM}\E//g' "$attic"
mas isso não fez nada.
Desde que você mencionou
zsh
, você poderia fazer:$mapfile
nozsh/mapfile
módulo há um array associativo especial que mapeia os nomes dos arquivos para seu conteúdo."${(0@)var}"
: divide$var
em NULs (e com@
aspas dentro de aspas preserva elementos vazios como"$@"
).${array:#pattern}
. remove os elementos que correspondem ao padrão. Aqui o conteúdo de$i
é tomado literalmente, você precisa$~i
que ele seja tomado como padrão (ou habilite aglobsubst
opção).${(j:string:)array}
: une os elementos do array comstring
. Comp
,\0
é convertido para NUL. (observe que o0
sinalizador de expansão de parâmetro acima também pode ser escritops:\0:
).Você pode obter algo semelhante
perl
com:A diferença é que
perl
adicionará um NUL no final se já não houver um (e os problemas usuais com-i
(quebrar links, não preservar todos os metadados ...)).Um equivalente mais próximo seria:
Sua
não funciona porque:
-pi0
: o0
é tomado como argumento para-i
(o sufixo do nome do arquivo de backup)-0pi
, isso não poderia ter funcionado, pois dizperl
para processar registros terminados em NUL , então o registro ($_
) terá o NUL no final, não no início. Use-0777
forperl
para processar a entrada como um registro contendo toda a entrada.Com base em seus dados de entrada e supondo que seu arquivo seja pequeno o suficiente para caber na memória, isso pode funcionar para você:
As
-0777
causasperl
para slurp o arquivo inteiro na memória. A$ENV{var}
é a maneira do perl de acessar variáveis de ambiente exportadas. Assim$ENV{i}
obterá o valor da variável exportadai
. Os/old/new/g
substituiráold
comnew
globalmente. O\Q
and\E
garante que o padrão não seja interpretado como uma expressão regular. Finalmente, o\n?
é necessário, pois o shell comerá novas linhas das extremidades das variáveis ao atribuir a saída de uma substituição de comando (por exemplovar=$(printf 'foo\n')
, ), portanto,$i
pode não incluir a nova linha final.Observe que isso também corresponderá a substrings. Portanto, se
i
forfoo
e seu arquivo contiverfoolish
, ofoo
será removido deixandoish
. Se você não quiser isso, você pode usar:Testando no seu exemplo (depois de substituir
^@
por\0
):Claro, isso pressupõe que
$i
não há nenhuma nova linha à direita. Eu não posso dizer se isso acontece ou não, poiscat <<<"$i"
adicionaria um, mesmo que não.Se você precisar fazer isso para uma matriz de shell, você pode fazer:
Importante : observe o
-i
no exemplo acima. Isso edita o arquivo no local, então faça backup antes de testar.