Copy link to clipboard
Copied
Hi Scripters,
Even if this seems to work, should I avoid this kind of writing? [line 20]
• Double loop while + for on the same "F"
• Find/Replace without "changeTo"
[ Original thread here: Repeated Volume Numbers in Index ]
redraw = app.scriptPreferences.enableRedraw;
app.scriptPreferences.enableRedraw = 0;
app.doScript("main()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "FindReplace! …");
app.scriptPreferences.enableRedraw = redraw;
function main()
{
var myDoc = app.activeDocument,
FindWhat1 = "(I+:\\h)(\\d+(,\\h)?)+\\K\\1",
FindWhat2 = "\\d+\\K,(?=\\hI+:\\h)", ReplaceBy2 = ";";
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = FindWhat1;
myFound = myDoc.findGrep();
var F = myFound.length;
while (F--) for (var f = 0; f < F; f++) myDoc.changeGrep();
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = FindWhat2;
app.changeGrepPreferences.changeTo = ReplaceBy2;
myDoc.changeGrep();
app.findGrepPreferences = app.changeGrepPreferences = null;
}
Thanks in advance!
(^/)
Copy link to clipboard
Copied
Even before considering code optimiation, I am troubled with the intention:
Line 20:
while (F--) for (var f = 0; f < F; f++) myDoc.changeGrep();
Ok so you want to loop through fingGrep results and do change. But myDoc.changeGrep() is global. So you are just processing teh whole doc over and over.
don't loop and just call myDoc.changeGrep() or if loop, prefer myFound
Plus, you are actually changing to nothing as change option are null (line 16) and not redefined.
Also you are "doing" the same thing twice. Set a F/C function and call it twice with a different set of properties.
Copy link to clipboard
Copied
app.doScript("main()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "FindReplace! …");
function main()
{
var sps = app.scriptPreferences.properties,
myDoc = app.properties.activeDocument,
fgp = app.findGrepPreferences.properties,
cgp = app.changeGrepPreferences.properties;
if( !myDoc ) return;
app.scriptPreferences.enableRedraw = false;
app.findGrepPreferences = app.changeGrepPreferences = null;
changeGrep ( myDoc, {
find : {
findWhat:"(I+:\\h)(\\d+(,\\h)?)+\\K\\1"
},
change : {
// ????
}
});
changeGrep ( myDoc, {
find : {
findWhat:"\\d+\\K,(?=\\hI+:\\h)"
},
change : {
changeTo:";"
}
});
app.findGrepPreferences.properties = fgp;
app.changeGrepPreferences.properties = cgp;
app.scriptPreferences.properties = sps;
}
function changeGrep(doc, props ) {
app.findGrepPreferences.properties = props.find;
app.changeGrepPreferences.properties = props.change;
doc.changeGrep();
}
FWIW
Loïc
Copy link to clipboard
Copied
Hi Loïc,
Thanks for your comments!
To be more explicite! …
I use 2 regex!
If I only used the ID Find/Replace window, I should need to play 4 times the first and 2 times the second to have a "zero" replace-counter:
Regex1:
Regex2:
… So, if you count the points, we have: (Regex1: 50 + 20 + 10 + 0) + (Regex2: 20 + 0) = 80 find/replace!
I've rewritten the script! My deal is to launch "x" times the regex1 because I know it won't find all the occurrences in one time!
So:
function main()
{
var myDoc = app.activeDocument,
FindWhat1 = "(I+:\\h)(\\d+(,\\h)?)+\\K\\1",
FindWhat2 = "\\d+\\K,(?=\\hI+:\\h)", ReplaceBy2 = ";";
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = FindWhat1;
myFound = myDoc.findGrep();
var F = myFound.length,
myCounter = 0;
for (var f = 0; f < F; f++) {
myChange1 = myDoc.changeGrep();
F = myChange1.length;
myCounter += F;
}
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = FindWhat2;
app.changeGrepPreferences.changeTo = ReplaceBy2;
myChange2 = myDoc.changeGrep();
app.findGrepPreferences = app.changeGrepPreferences = null;
myCounter += myChange2;
alert( "Counter: "+ myCounter + " treated! (^/) ;-)" )
}
What I'm trying to get is having a first estimation of "F", run x (<= F) times the regex1 [see lines 07 + 14].
When "F" will be equal to 0 [see line 13], the "for" loop will be finished and, so, the "while" loop will be finished too!!
At this moment, the script could run the Regex2!
As you see, this 2nd version works but surely a more orthodox way, based on these 2 regex!
Of course, I could use Multi-Find/change and do it directly with a 30-seconds work but it's not the problematic!
(^/)
Copy link to clipboard
Copied
Given the following sample
xxx xxxx I: 23, I: 35, II: 48, II: 68
xxx xxxx I: 23, I: 35, II: 48, II: 68
xxx xxxx I: 23, I: 35, II: 48, II: 68
xxx xxxx I: 23, I: 35, II: 48, II: 68
xxx xxxx I: 23, I: 35, II: 48, II: 68
app.doScript("main()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "FindReplace! …");
function main()
{
var sps = app.scriptPreferences.properties,
myDoc = app.properties.activeDocument,
fgp = app.findGrepPreferences.properties,
cgp = app.changeGrepPreferences.properties,
found, n;
if( !myDoc ) return;
app.scriptPreferences.enableRedraw = false;
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "(I+:\\h\\d+(,\\h)?)+" ;
found = myDoc.findGrep();
n = found.length;
n && processResults( found );
app.findGrepPreferences.properties = fgp;
app.changeGrepPreferences.properties = cgp;
app.scriptPreferences.properties = sps;
}
function processResults ( aTexts ) {
var n = aTexts.length, aText;
while ( n-- ) {
aText = aTexts
; aText.contents = getNewContents ( aText.contents );
}
}
function getNewContents ( content ) {
var iSeps = content.match( /I+: \d+/g ), n, newContent = [], o = {}, split;
if ( !iSeps ) return content;
n = iSeps.length;
iSeps.reverse();
while ( n-- ) {
split = iSeps
.split(": "); o[split[0]]=o[split[0]] || [];
o[split[0]].push( split[1] );
}
for ( prop in o ) {
newContent.push ( prop+": "+o[prop].join(", ") );
}
return newContent.join("; ");
}
will do
xxx xxxx I: 23, 35; II: 48, 68
xxx xxxx I: 23, 35; II: 48, 68
xxx xxxx I: 23, 35; II: 48, 68
xxx xxxx I: 23, 35; II: 48, 68
xxx xxxx I: 23, 35; II: 48, 68
HTH
Loic
Copy link to clipboard
Copied
Thanks Loïc! I'm going to study and trying to understand this version (now)!
My new version is very fast: 38" to treat 50,000 items!
redraw = app.scriptPreferences.enableRedraw;
app.scriptPreferences.enableRedraw = 0;
app.doScript("main()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "FindReplace! …");
app.scriptPreferences.enableRedraw = redraw;
function main()
{
var myDoc = app.activeDocument,
myZeroCounter1 = 1, myZeroCounter2 = 1,
myCounter1 = 0, myCounter2 = 0;
while (myZeroCounter1--) Change1();
while (myZeroCounter2--) Change2();
alert( "Counter: " + Number(myCounter1 + myCounter2) + " treated! (^/) ;-)" )
function Change1() {
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "(I+:\\h)(\\d+(,\\h)?)+\\K\\1";
app.changeGrepPreferences.changeTo = "";
myChange1 = myDoc.changeGrep();
myZeroCounter1 = myChange1.length;
myCounter1 += myZeroCounter1;
}
function Change2() {
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findGrepPreferences.findWhat = "\\d+\\K,(?=\\hI+:\\h)";
app.changeGrepPreferences.changeTo = ";";
myChange2 = myDoc.changeGrep();
myZeroCounter2 = myChange2.length;
myCounter2 += myZeroCounter2;
}
app.findGrepPreferences = app.changeGrepPreferences = null;
}
(^/)