Поиск и замена участка кода в файле.

ЕСТЬ РЕШЕНИЕ ЗАКРЫТО

Помогите новичку в PHP

#16 18 июня 2014 в 22:59
Скорпион, набросал пример:
  1. <?php
  2. $orig=file("orig.php");
  3. $search=file("search.php");
  4. $replace=file("replace.php");
  5. //print_r($search);
  6. $result=$orig;
  7. $n=array_search($search[0],$orig);
  8. $orig_slice=array_slice($orig,$n,sizeof($search)); //кусок массива для вырезки
  9. $orig_start=array_slice($orig,0,$n); //кусок до вырезки
  10. $orig_end=array_slice($orig,$n+sizeof($search)); //кусок после вырезки
  11. //print_r($orig_end);
  12. $flag=array();
  13. for ($i=0;$i<sizeof($search);$i++){
  14. $a=trim(str_replace("\n","",$orig_slice[$i]));
  15. $b=trim(str_replace("\n","",$search[$i]));
  16. if($a==$b){ //сравниваем содержимое строк
  17. echo $i. " <font color='green'>совпало ".htmlspecialchars($b)."</font><br>";
  18. $flag[]=1;
  19. } else{
  20. echo $i. " <font color='red'>нет ".htmlspecialchars($b)."</font><br>";
  21. $flag[]=0;
  22. }
  23. }
  24. print_r($flag);
  25. if(!array_search("0",$flag)){
  26. $result=array_merge($orig_start,$replace,$orig_end);
  27. print_r($result);
  28. }
  29. ?>
  30.  
#17 19 июня 2014 в 11:52
Спасибо за пример. Неплохо.
Однако вы не учли вот что.
Во первых кусок кода который нужно найти и поменять, может встречаться не один раз.
Во вторых мне кажется не достаточно trim-нуть сравниваемые строчки. Как я правильно понял — эта команда убирает лишние пробелы в начале и конце строчки. А как быть на счет лишних пробелов внутри строчки
ведь например вот эти две строчки при сравнении не будут равны:

  1. $a = 1;
  2. $a=1;
Но все равно спасибо за пример.
Я седня попытаюсь добить свой вариант и тоже вылажу для ознакомления.
#18 19 июня 2014 в 15:16
Скорпион, если это оформить в функцию, то ее можно применить и не один раз. Если недостаточно тримнуть, то можно перед сравнением применять любые строковые функции, чтобы привести их к общему знаменателю — привести в один регистр, удалить комменты, удалить все пробелы и т.п.
  1.  
  2. $bad=array("\n"," ","/","&");//любые символы которые не нужны при сравнении
  3. $a=strtolower(str_replace($bad,"",$orig_slice[$i]);
  4. $b=strtolower(str_replace($bad,"",$search[$i]);
  5.  
#19 19 июня 2014 в 15:22
snooker, о! а я все сообразить не могу как заменять не по одному искомому символу а одновременно.....:)
#20 19 июня 2014 в 15:24
Это я про это:
  1. $bad=array("\n"," ","/","&");
#22 19 июня 2014 в 15:34
Вот чего я наваял на данный момент :)
  1.  
  2. // функция для очистки строки от пробелов и табуляции
  3. function ChangeSimbolSpace($str){
  4. $str = str_replace("\t","", $str);
  5. $str = str_replace(" ","", $str);
  6. return trim($str);
  7. }
  8. // функция для очистки строк от кодов перевода и окончания строки
  9. function ChangeSimbolNull($str){
  10. $str = str_replace("\r","", $str);
  11. $str = str_replace("\n","", $str);
  12. return $str;
  13. }
  14. // функция для удаления из массива пустых строк
  15. function ClearArrayEmpty($array){
  16. $ret_arr = array();
  17. foreach($array as $val){
  18. $key = ChangeSimbolNull($val);
  19. if (!empty($key)){
  20. $ret_arr[] = $val;
  21. }
  22. }
  23. return $ret_arr;
  24. }
  25.  
  26.  
  27.  
  28.  
  29. $search = file($search_file); // массив с кодом для поиска
  30. $replace = file($replace_file); // массив с кодом для замены
  31. $in = file($in_file); // массив с исходным кодом
  32.  
  33. // создаем временные массивы данных без пустых строк
  34. $temp_search = ClearArrayEmpty($search);
  35. $temp_replace = ClearArrayEmpty($replace);
  36. $temp_in = ClearArrayEmpty($in);
  37.  
  38.  
  39. foreach($temp_in as $k => $str_in){ // проверкамассива с исходным кодом
  40. $str_in_key = $str_in; // создание ключа проверяемой строчки исходного кода, чтобы не изменять код массива
  41. $str_search_key = $temp_search[0]; // создание ключа ПЕРВОЙ строчки для поиска, чтобы не изменять код массива
  42.  
  43. if (ChangeSimbolSpace($str_in_key) == ChangeSimbolSpace($str_search_key)){ // при совпадении ОЧИЩЕННЫХ от пробелов проверяемой и первой искомой строк
  44. $slice_in = array_slice($temp_in, $k, sizeof($temp_search)); // создаем срез исходных данных от совпавшей строки и длинной равной длине искомого кода
  45. $search_flag[$k] = 1; // создаем массив найденных совпадений, где ключ массива равен ключу совпавшей строки в массиве с исходным кодом.
  46. foreach ($slice_in as $kk => $str_slice_in){ // проверяем срез исходного кода на 100% совпадение с массивом кода для поиска
  47. if (ChangeSimbolSpace($str_slice_in) != ChangeSimbolSpace($temp_search[$kk])){ // если ОЧИЩЕННЫЕ от пробелов сравниваемы строки , хотябы раз не совпадут
  48. $search_flag[$k]= 0; // "обнуляем данные" в массиве совпадений
  49. break; // и прекращаем проверку среза
  50. }
  51. }
  52. }
  53. }
  54.  
На выходе получаем массив $search_flag с указанием в нем строки массива с исходным кодом где нужно произвести замену.
#23 19 июня 2014 в 15:41
Скорпион, можно окультурить — array_walk
#24 19 июня 2014 в 15:43
Пойду читать что это такое :)
#25 19 июня 2014 в 22:38

  1.  
  2. // функция для очистки строки от пробелов и табуляции
  3. function ChangeSimbolSpace($str){
  4. $str = str_replace("\t","", $str);
  5. $str = str_replace(" ","", $str);
  6. return trim($str);
  7. }
  8. // функция для очистки строк от кодов перевода и окончания строки
  9. function ChangeSimbolNull($str){
  10. $str = str_replace("\r","", $str);
  11. $str = str_replace("\n","", $str);
  12. return $str;
  13. }
  14. // функция для удаления из массива пустых строк
  15. function ClearArrayEmpty($array){
  16. $ret_arr = array();
  17. foreach($array as $val){
  18. $key = ChangeSimbolNull($val);
  19. if (!empty($key)){
  20. $ret_arr[] = $val;
  21. }
  22. }
  23. return $ret_arr;
  24. }
  25.  
  26.  
  27.  
  28. $search = file($search_file); // массив с кодом для поиска
  29. $replace = file($replace_file); // массив с кодом для замены
  30. $in = file($in_file); // массив с исходным кодом
  31.  
  32. // создаем временные массивы данных без пустых строк
  33. $temp_search = ClearArrayEmpty($search);
  34. $temp_replace = ClearArrayEmpty($replace);
  35. $temp_in = ClearArrayEmpty($in);
  36.  
  37. $search_flag_temp = array();
  38. foreach($temp_in as $k => $str_in){ // проверка массива с исходным кодом
  39. $str_in_key = $str_in; // создание ключа проверяемой строчки исходного кода, чтобы не изменять код массива
  40. $str_search_key = $temp_search[0]; // создание ключа ПЕРВОЙ строчки для поиска, чтобы не изменять код массива
  41.  
  42. if (ChangeSimbolSpace($str_in_key) == ChangeSimbolSpace($str_search_key)){ // при совпадении ОЧИЩЕННЫХ от пробелов проверяемой и первой искомой строк
  43. $slice_in = array_slice($temp_in, $k, sizeof($temp_search)); // создаем срез исходных данных от совпавшей строки и длинной равной длине искомого кода
  44. $search_flag_temp[$k] = 1; // создаем массив найденных совпадений, где ключ массива равен ключу совпавшей строки в массиве с исходным кодом.
  45. foreach ($slice_in as $kk => $str_slice_in){ // проверяем срез исходного кода на 100% совпадение с массивом кода для поиска
  46. if (ChangeSimbolSpace($str_slice_in) != ChangeSimbolSpace($temp_search[$kk])){ // если ОЧИЩЕННЫЕ от пробелов сравниваемы строки , хотябы раз не совпадут
  47. $search_flag_temp[$k] = 0; // "обнуляем данные" в массиве совпадений
  48. break; // и прекращаем проверку среза
  49. }
  50. }
  51. }
  52. }
  53. $search_flag = array(); // приводим массив совпадений в потребный вид и удаляем строки с ложными срабатываниями.
  54. foreach ($search_flag_temp as $number => $flags){
  55. if ($flags == 1){
  56. $search_flag[]= $number;
  57. }
  58. }
  59.  
  60. $out = $temp_in;
  61. $replace_start = 0;
  62. $replace_end = 0;
  63.  
  64. foreach ($search_flag as $shift_key => $shift){
  65. $replace_start = $shift + (sizeof($temp_replace) - sizeof($temp_search)) * $shift_key;
  66. $replace_end = $replace_start + sizeof($temp_search);
  67. $slice_out_start = array_slice($out, 0, $replace_start);
  68. $slice_out_end = array_slice($out, $replace_end);
  69. $out = array_merge($slice_out_start, $temp_replace, $slice_out_end);
  70. }
  71.  
В массиве $out в итоге имеем необходимый результат. Задача решена. :)
#26 19 июня 2014 в 22:42
Фух.....:)
Следующим шагом надо разобраться как заменить на сервере исходный файл патченым.
В рамках ICMS2 конечно.
#27 19 июня 2014 в 23:25
Скорпион, наверно сначала надо сохранить копию fopen,fwrite,fclose, проверить размер и заменить исходник, оригинал перед этим сохрянить рядом. Насчет рамок ICMS2 я сомневаюсь, уже не так, так что делайте универсальный патчер)
#28 20 июня 2014 в 15:49
snooker, если интересно дальнейшее обсуждение "основной цели" сабжа, то предлагаю перенести разговор в родительскую тему.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.