libsheepy

C lib for handling text files, strings and json like data structure with an object oriented system
git clone https://spartatek.se/git/libsheepy.git
Log | Files | Refs | README | LICENSE

search_and_replace_strings_in_files.c (6079B)


      1 //#!/usr/bin/tcc -run
      2 // search and replace
      3 // input:
      4 //   file.txt
      5 //   replace_configuration.txt
      6 // the files to process are listed in file.txt in current directory.
      7 // Use # to comment lines in files.txt.
      8 // replace_configuration.txt holds the strings to search and replace in the files listed in file.txt
      9 //
     10 // replace_configuration.txt format:
     11 //  - line 1: separetor in line 2 and 3
     12 //  - line 2: strings to search separeted with the characters in line 1
     13 //  - line 3: replace strings separeted with the characters in line 1
     14 
     15 #include "../release/libsheepy.h"
     16 #include "../release/libsheepy.c"
     17 #include "pcre.h"
     18 
     19 #define internal static
     20 
     21 #include <stdlib.h>
     22 #include <stdbool.h>
     23 #include <string.h>
     24 #include <stdio.h>
     25 
     26 void replace();
     27 void replaceWithPcre(char **l, pcre *reCompiled, pcre_extra *pcreExtra, char *replaceWith);
     28 #ifndef unitTest
     29 #endif
     30 int MAIN(int ARGC, char** ARGV);
     31 
     32 int argc; char **argv;
     33 
     34 void replace() {
     35     char **replace_configuration = NULL;
     36     char **search_what = NULL;
     37     char **replace_with = NULL;
     38     char **config = NULL;
     39 
     40     // Steps
     41     // load config
     42     // create string regex
     43     // compile regexes
     44     // optimize the regex
     45     // create regex for each search string
     46     // for each file in files.txt, search and replace
     47 
     48     printf("\nLoading config...\n");
     49     printf("\n");
     50 
     51     // load config
     52     replace_configuration = readText("replace_configuration.txt");
     53 
     54     exitFailure(replace_configuration);
     55 
     56     search_what  = split(replace_configuration[1], replace_configuration[0]);
     57     replace_with = split(replace_configuration[2], replace_configuration[0]);
     58 
     59     if (!search_what || !replace_with) {
     60       printf("wrong replace_configuration.txt");
     61       printf("\n");
     62       XFAILURE;
     63     }
     64 
     65     // create string regex
     66     char **strRegex = NULL;
     67     enumerateCharP(search_what, e, i) {
     68         printf("Replace: ");
     69         printf("\n");
     70         printf("%s\n", *e);
     71         printf("With:");
     72         printf("\n");
     73         printf("%s\n", replace_with[i]);
     74         char *reg = catS("\\b", *e, "\\b");
     75         pErrorNULL(iListPushS(&strRegex, reg));
     76     }
     77 
     78     //listPrintS(strRegex);
     79 
     80     // compile regexes
     81     // optimize the regex
     82     size_t nSearch = listLengthS(search_what);
     83     pcre **reCompiled = malloc((nSearch+1) * sizeof(pcre *));
     84     reCompiled[nSearch] = NULL;
     85     pcre_extra **pcreExtra = malloc((nSearch+1) * sizeof(pcre_extra *));
     86     pcreExtra[nSearch] = NULL;
     87 
     88     const char *pcreErrorStr;
     89     int pcreErrorOffset;
     90 
     91     // create regex for each search string
     92     enumerateCharP(strRegex, e, j) {
     93       reCompiled[j] = pcre_compile(*e, 0, &pcreErrorStr, &pcreErrorOffset, NULL);
     94       if (!reCompiled[j]) {
     95         printf("ERROR: Could not study >%s<: %s", *e, pcreErrorStr);
     96         printf("\n");
     97         XFAILURE;
     98       }
     99 
    100       pcreExtra[j] = pcre_study(reCompiled[j], 0, &pcreErrorStr);
    101       if (!pcreExtra) {
    102         printf("ERROR: Could not study >%s<: %s", *e, pcreErrorStr);
    103         printf("\n");
    104         XFAILURE;
    105     }
    106       }
    107 
    108 
    109     printf("\n\nProcess files...\n");
    110     printf("\n");
    111 
    112     config = readText("files.txt");
    113     exitFailure(config);
    114 
    115     // for each file in files.txt, search and replace
    116     forEachCharP(config, f) {
    117         if (!isBlankS(*f)) {
    118             if (*f[0] != '#') {
    119                 pErrorNULL(iTrimS(f));
    120                 char **src = readText(*f);
    121                 if (!src) {
    122                     printf("Cant read file %s", *f);
    123                     printf("\n");
    124                     continue;
    125                 }
    126 
    127                 // scan lines
    128                 forEachCharP(src, l) {
    129                     enumerateCharP(search_what, a, i) {
    130                         //iReplaceS_max(l, *a, replace_with[i]);
    131                         replaceWithPcre(l, reCompiled[i], pcreExtra[i], replace_with[i]);
    132                 }
    133                     }
    134 
    135                 bool status = writeText(*f, src);
    136                 if (status) {
    137                     printf("CHANGED:      %s", *f);
    138                     printf("\n");
    139                 }
    140                 else {
    141                     printf("DIDNT CHANGE: %s", *f);
    142                     printf("\n");
    143     }
    144         }
    145             }
    146                 }
    147 
    148     listFreeManyS(replace_configuration, search_what, replace_with, config, strRegex);
    149 
    150     forEachType(pcre, reCompiled, e) {
    151       pcre_free(*e);
    152     }
    153     free(reCompiled);
    154 
    155     if (pcreExtra[0]) {
    156       forEachType(pcre_extra, pcreExtra, e) {
    157         #ifdef PCRE_CONFIG_JIT
    158         pcre_free_study(*e);
    159         #else
    160         pcre_free(*e);
    161         #endif
    162     }
    163       }
    164     free(pcreExtra);
    165 }
    166 
    167 void replaceWithPcre(char **l, pcre *reCompiled, pcre_extra *pcreExtra, char *replaceWith) {
    168     int r;
    169     int subStrVec[30];
    170     size_t len;
    171     size_t offset = 0;;
    172     int allMatch[100];
    173     size_t nMatch = 0;;
    174 
    175     len = strlen(*l);
    176     r = pcre_exec(reCompiled, pcreExtra, *l, len, 0, 0, subStrVec, 30);
    177 
    178     while ((offset < len) && (r >= 0)) {
    179 
    180         if (r == 0) {
    181             printf("But too many substrings were found to fit in subStrVec!\n");
    182             r = 30/3;
    183         }
    184 
    185         for (int j=0; j < r; j++) {
    186             allMatch[nMatch]   = subStrVec[j*2];
    187             allMatch[nMatch+1] = subStrVec[j*2+1];
    188             nMatch            += 2;
    189         }
    190 
    191         offset = subStrVec[1];
    192         r = pcre_exec(reCompiled, pcreExtra, *l, len, offset, 0, subStrVec, 30);
    193     }
    194 
    195     if (!nMatch) {
    196       return;
    197     }
    198 
    199     for (int i = nMatch ; i > 0 ; i-=2) {
    200       // replace word
    201       char *sBefore = emptySF();;
    202 
    203       if (allMatch[i-2]) {
    204         // 0 means end of string
    205         sBefore = sliceS(*l, 0, allMatch[i-2]);
    206       }
    207 
    208       char *sAfter  = sliceS(*l, allMatch[i-1], 0);
    209       free(*l);
    210       *l = catS(sBefore, replaceWith, sAfter);
    211       freeManyS(sBefore, sAfter);
    212 }
    213     }
    214 
    215 // -------------------------------------------------------------------------------------
    216 
    217 #ifndef unitTest
    218 // Remove main when running the unit tests
    219 #define MAIN   main
    220 #endif
    221 int MAIN(int ARGC, char** ARGV) {
    222     int dum UNUSED;
    223 
    224     argc = ARGC; argv = ARGV;;//
    225 
    226     replace();
    227 
    228     XSUCCESS;
    229 }