valor - recorrer string php
Buscar recursivamente todos los directorios para una matriz de cadenas en php (1)
Soy nuevo en la codificación de PHP y aquí estoy buscando la forma más rápida de realizar búsquedas recursivas en todos los directorios para una serie de cadenas.
Lo estoy haciendo de esta manera
$contents_list = array("xyz","abc","hello"); // this list can grow any size
$path = "/tmp/"; //user will give any path which can contain multi level sub directories
$dir = new RecursiveDirectoryIterator($path);
foreach(new RecursiveIteratorIterator($dir) as $filename => $file) {
$fd = fopen($file,''r'');
if($fd) {
while(!feof($fd)) {
$line = fgets($fd);
foreach($contents_list as $content) {
if(strpos($line, $content) != false) {
echo $line."/n";
}
}
}
}
fclose($fd);
}
Aquí estoy iterando recursivamente sobre todos los directorios y luego de nuevo en cada archivo iterar sobre la matriz de contenidos para buscar.
¿Hay alguna forma mejor de hacer un tipo de búsqueda? Por favor sugiera una alternativa más rápida.
Gracias
Si tiene permiso para ejecutar comandos de shell en su entorno (y suponiendo que está ejecutando su script en * nix), puede llamar al comando grep nativo recursivamente. Eso te daría los resultados más rápidos.
$contents_list = array("xyz","abc","hello");
$path = "/tmp/";
$pattern = implode(''/|'', $contents_list) ;
$command = "grep -r ''$pattern'' $path";
$output = array();
exec($command, $output);
foreach ($output as $match) {
echo $match . ''/n'';
}
Si la directiva disable_functions
está en vigencia y no puede llamar a grep, podría usar su enfoque con RecursiveDirectoryIterator
y leer los archivos línea por línea, utilizando strpos en cada línea. Tenga en cuenta que strpos
requiere una estricta comprobación de igualdad ( !== false
use !== false
lugar de != false
), de lo contrario, saltará las coincidencias al comienzo de una línea.
Una forma un poco más rápida es usar glob recusivamente para obtener una lista de archivos, y leer esos archivos a la vez en lugar de escanearlos línea por línea. De acuerdo con mis pruebas, este enfoque le dará una ventaja de tiempo de 30-35% sobre la suya.
function recursiveDirList($dir, $prefix = '''') {
$dir = rtrim($dir, ''/'');
$result = array();
foreach (glob("$dir/*", GLOB_MARK) as &$f) {
if (substr($f, -1) === ''/'') {
$result = array_merge($result, recursiveDirList($f, $prefix . basename($f) . ''/''));
} else {
$result[] = $prefix . basename($f);
}
}
return $result;
}
$files = recursiveDirList($path);
foreach ($files as $filename) {
$file_content = file($path . ''/'' . $filename);
foreach ($file_content as $line) {
foreach($contents_list as $content) {
if(strpos($line, $content) !== false) {
echo $line . ''/n'';
}
}
}
}
El crédito para la función glob recursiva va a http://proger.i-forge.net/3_ways_to_recursively_list_all_files_in_a_directory/Opc
Para resumir, desde el punto de vista del rendimiento tiene los siguientes rankings (resultados en segundos para un directorio muy grande que contiene ~ 1200 archivos recusivamente, usando dos patrones de texto comunes):
- llame a grep a través de exec () - 2.2015s
- use
glob
recursivo y lea archivos confile()
- 9.4443s - use
RecursiveDirectoryIterator
y lea archivos conreadline()
- 15.1183s