Linha Substituir na arquivo com PHP
Pergunta
O que é a melhor maneira de substituir uma linha específica em um arquivo? Basicamente, eu quero procurar um arquivo para a string '@parsethis' e substituir o resto da linha com outra coisa.
Solução
Se o arquivo não é muito grande, a melhor maneira seria provavelmente para ler o arquivo em uma matriz de linhas com () , pesquisar o conjunto de linhas para a sua corda e editar essa linha, então implode () a matriz de volta juntos e fwrite () -lo de volta para o arquivo.
Outras dicas
Se o arquivo é muito grande (arquivos de log ou algo assim) e você está disposto a sacrificar a velocidade de consumo de memória que você poderia abrir dois arquivos e essencialmente fazer o truque Jeremy Ruten proposto usando arquivos em vez de memória do sistema.
$source='in.txt';
$target='out.txt';
// copy operation
$sh=fopen($source, 'r');
$th=fopen($target, 'w');
while (!feof($sh)) {
$line=fgets($sh);
if (strpos($line, '@parsethis')!==false) {
$line='new line to be inserted' . PHP_EOL;
}
fwrite($th, $line);
}
fclose($sh);
fclose($th);
// delete old source file
unlink($source);
// rename target file to source file
rename($target, $source);
Seu principal problema é o fato de que a nova linha pode não ser o mesmo comprimento que a antiga linha. Se você precisar alterar o comprimento da linha, não há nenhuma maneira de sair de reescrever pelo menos todos o arquivo após a linha alterada. A maneira mais fácil é criar um arquivo novo, modificado e, em seguida, movê-lo sobre o original. Desta forma, não é um arquivo completo disponível em todos os momentos para os leitores. Use bloqueio para se certificar de que apenas um script é modificar o arquivo de uma vez, e uma vez que você está indo para substituir o arquivo, faça o bloqueio em um arquivo diferente. Confira flock()
.
Se você tiver certeza de que a nova linha será o mesmo comprimento que a linha de idade, você pode abrir o arquivo em modo de leitura / escrita (uso r+
como o segundo argumento para fopen()
) e ftell()
chamada para salvar a posição da linha começa em cada tempo antes de chamar fgets()
para ler uma linha. Depois de encontrar a linha que você deseja substituir, você pode usar fseek()
para voltar ao início da linha e fwrite()
os novos dados. Uma maneira de forçar a linha a ser sempre o mesmo comprimento é para preencher o espaço-lo para o comprimento máximo possível.
ou se o arquivo não é muito grande:
$sample = file_get_contents('sample');
$parsed =preg_replace('#@parsethis.*#', 'REPLACE TO END OF LINE', $sample);
Você terá que escolher delimitadores '#', que não estão presentes no arquivo embora.
Esta é uma solução que funciona para reescrever apenas uma linha de um arquivo no lugar com sed de PHP. Meu arquivo contém apenas estilo Vars e é formatado:
$ StyleVarName: styleVarProperty; \ n
Por isso eu primeiro adicionar o ":" até os confins da myStyleVarName e substitui sed o resto dessa linha com a nova propriedade e acrescenta um ponto e vírgula.
Fazer personagens certeza que estão devidamente escapou em myStyleVarProp.
$command = "pathToShellScript folder1Name folder2Name myStyleVarName myStyleVarProp";
shell_exec($command);
/* shellScript */
#!/bin/bash
file=/var/www/vhosts/mydomain.com/$1/$2/scss/_variables.scss
str=$3"$4"
sed -i "s/^$3.*/$str;/" $file
Se você quiser substituir completamente o conteúdo de um arquivo com o conteúdo de outro arquivo que você pode usar isto:
rename("./some_path/data.txt", "./some_path/data_backup.txt");
rename("./some_path/new_data.txt", "./some_path/data.txt");
Assim, na primeira linha que você faça backup do arquivo e na segunda linha você substituir o arquivo com o conteúdo de um novo arquivo.
Tanto quanto eu posso dizer a renomeação retorna um booleano. Verdadeiro se a renomeação é bem sucedida e false se ele falhar. Pode-se, portanto, só executar a segunda etapa se o primeiro passo é bem sucedida para evitar substituindo o arquivo a menos que um backup foi feito com sucesso. Confira:
https://www.php.net/manual/en/function .rename.php
A esperança que seja útil para alguém.
Felicidades
Adrian
Eu provavelmente fazer o que Jeremy sugerido, mas apenas para uma forma alternativa de fazer isso aqui é uma outra solução. Este não foi testado ou usado e é para os sistemas * nix.
$cmd = "grep '@parsethis' " . $filename;
$output = system($cmd, $result);
$lines = explode("\n", $result);
// Read the entire file as a string
// Do a str_repalce for each item in $lines with ""