Hi, I am trying to find this string "QuickSearchResultsCOnfig" in a text file. The text file will contain this in several places. I need the following

var QuickSearchResultsConfig = ['a','b','v','d','e

I need to replace the above with

var QuickSearchResultsConfig = [['a',{hidden:true}],['b', {hidden:true}],'v','d','e
                                        'f','g '];

My original approach:
Store a,b,c,d,e,f,g in a list []
Read file line by line
For every line
if line contains "QuickSearchResultsConfig"
then for every item in list[]
replace item by '['+item+',hidden:true}],
This doestn work

Any simple efficient ways of doing this?

Two things:
First thing is to do the change carefully so you can back out on failure. The steps are

  1. read the file into memory
  2. update the memory version of the file
  3. write the file to a new name (maybe [I]original[/I].tmp or the like)
  4. rename the original file (maybe [I]original[/I].bak or the like)
  5. rename the new file to the original name

Next is to use the re package and the sub method of a compiled regular expression. For example, here's a brief test:

import re

qsSa = r"(QuickSearchResultsConfig[ ]*=[ ]*\[.*)'a'(.*\];)"
qsREa = re.compile(qsSa)
qsSb = r"(QuickSearchResultsConfig[ ]*=[ ]*\[.*)'b'(.*\];)"
qsREb = re.compile(qsSb)

linesFromFile = [
  "This line untouched\n",
  "This changes: QuickSearchResultsConfig=['a','b','v','d','e','f'];\n",
  "This changes: QuickSearchResultsConfig = ['a','b','v','d','e','f'];\n",

for line in linesFromFile:
  print("IN:  %s"%(line.rstrip()))
  line = qsREa.sub(r"\1['a',{hidden:true}]\2",line)
  line = qsREb.sub(r"\1['b',{hidden:true}]\2",line)
  print("OUT: %s"%(line.rstrip())) 
IN:  This line untouched
OUT: This line untouched
IN:  This changes: QuickSearchResultsConfig=['a','b','v','d','e','f'];
OUT: This changes: QuickSearchResultsConfig=[['a',{hidden:true}],['b',{hidden:true}],'v','d','e','f'];
IN:  This changes: QuickSearchResultsConfig = ['a','b','v','d','e','f'];
OUT: This changes: QuickSearchResultsConfig = [['a',{hidden:true}],['b',{hidden:true}],'v','d','e','f'];

You should be able to handle both the 'a' and 'b' case at the same time, but the regular expressions above trades that for code that is a little simpler. To go that route, you would need to do more like what you suggested by testing if the line matches first, then doing a sub on smaller bits only if the line matches. This technique uses a more complete match so the substitution will only happen on appropriate lines, but at the cost of having more than one call to substitute each character at a time.

P.S. I would seriously consider doing this with sed if you are in a unix-like environment. The "first thing" remains much the same, but the job is done with a tool that's designed for exactly this purpose.

This article has been dead for over six months. Start a new discussion instead.