Error in illustrator regex text replace script

Explorer ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

如何在Illustrator中执行通配符/ GREP / 正则表达式查找替换?- 平面设计堆栈交换

 

 

测试后,以下元字符未正确执行:^ $ /n (?<=) (?<!)(?=)(?!)

谁可以帮助我修改它

 

TOPICS
Bug , Draw and design , Scripting

Views

204

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , Dec 19, 2021 Dec 19, 2021
I tend to over-complicate things so you may want a simpler solution, but if I were to rewrite the function you've shown me I would do it like this: var options = { // Bypass all find/replace prompts, just remove the newlines: removeNewlines: false, // find: { value: "[\\r\\n\\cC]", // Text to appear as default title: "Find:", // Title of window desc: "Enter RegExp/GREP/Text", // Description of window flags: "gm", }, replace: { value: "", title: "Replace:", ...

Likes

Translate

Translate
Explorer ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

After testing, the following metacharacters are not executed correctly: ^ $ /n (?<=) (?<!) (?=) (?!)

 

Who can help me modify it

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

Are you sure that ^, $, \n are not executed correctly? I've never noticed any issues there.

 

Negative and positive lookbehinds like (?<=) and (?<!) were not added to Javascript until much later than what is supported in Extendscript. You can often replicate them through lookaheads but that depends on the complexity of the expression.

 

Negative and positive lookaheads are supported:

 

// Positive lookahead:
var regex = /First(?= test)/g;

var test1 = 'First test'.match(regex),
    test2 = 'First peach'.match(regex),
    test3 = 'This is a First test in a year.'.match(regex),
    test4 = 'This is a First peach in a month.'.match(regex)

alert(test1) // ['First'], correct
alert(test2) // null, correct
alert(test3) // ['First'], correct
alert(test4) // null, correct
// Negative lookahead:
var result = /\d+(?!\.)/g.exec('3.141');

alert(result) // '141', correct
alert(result.index) // 2, correct
alert(result.input) // '3.141', correct

 

May be a syntax error with your code?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

please elaborate, what's the initial string and what's the result you're after?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

微信图片_20211217104122.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

Solved: Find and change mutliple texts in illustrator and ... - Adobe Support Community - 10484449

 

ai_re/ai_re_v1.5.zxp at master · dumbm1/ai_re · GitHub

 

It can help me here, but it must select the text box. I want to find and replace without selecting the text

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

Isn't newline/linefeed character specific to OS? For instance on Windows, a normal press of Enter produces 003 shown on left with "Lorem ipsum dolor" and Control+Enter produces 015 shown on right with "hello world".

 

ice_screenshot_20211216-201346.png

You can always identify a character via String.charCodeAt() to get the ASCII value to see exactly what character is being used for newlines (whether /r, /n, /r/n, or even ^z) then use caret syntax like above \c_ to target it.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

thank you!

 

Although I don't understand JavaScript language, I learned it for two days. I understand your code, but I can't really modify it.

 

The following is the author's original code. Note that this is the grep script in illustrator.

How to do a wildcard / GREP / regex find-replace in Illustrator? - Graphic Design Stack Exchange

Regex text replace.js

 

var scope = app.activeDocument.selection.length ? app.activeDocument.selection : app.activeDocument.pageItems;

var find = prompt("Find: (Text or GREP/regex)","");
if(find !== null){

    var replace = prompt("Replace: (Text or GREP/regex)","");
    if(replace !== null){

        var changes = 0;

        for(var i=0;i<scope.length;i++){  

            var text = scope[i];

            var string = text.contents;  
            if(typeof string == "string"){
                var newstring = string.replace( new RegExp(find, 'g'), replace);
                if (newstring != string) {
                    changes++;
                    var paragraphsArray = newstring.split("\n");
                    text.paragraphs.removeAll(); 
                    for(var ii=0;ii<paragraphsArray.length;ii++){  
                         text.paragraphs.add(paragraphsArray[ii]);
                    }
                }
            }
        }
        alert( changes==1 ? "1 text object changed" : changes + " text objects changed");
    }
}

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

No worries. I'm not sure I understand though, you want to find and replace text and I understand that you want to find newlines but what are you trying to replace them with?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 16, 2021 Dec 16, 2021

Copy link to clipboard

Copied

1.  /n

I know this is not very important, but I want to fix them because sometimes I want to delete it.

2. ^、$

These two are very important to me. I think there is any way to achieve them, like the following.

微信图片_20211217150229.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 17, 2021 Dec 17, 2021

Copy link to clipboard

Copied

I can't really speak to the accuracy of the CEP panel you're using, but if you wanted to delete newlines this could be done like so:

var find = /[\r\n\cC]/gm,
    replace = " ";

var texts = app.activeDocument.textFrames;

for (var i = 0; i < texts.length; i++)
    texts[i].contents = texts[i].contents.replace(find, replace);

 

With regards to ^, you can split the string, process each line, then join and replace it:

var find = /^./gm,
    replace = "2"

var doc = app.activeDocument,
    texts = doc.textFrames;

for (var i = 0; i < texts.length; i++) {
    var content = texts[i].contents;
    var lines = content.split(/[\r\n\cC]/gm),
        newStr = []
    for (var e = 0; e < lines.length; e++)
        newStr.push(lines[e].replace(find, replace));
    texts[i].contents = newStr.join("\r\n");
}

 

Before running we have two TextFrameItems, the one at the top has word-wrapping and no newline but the TextFrame at the bottom ("foo, test, hello") has two newlines:

ice_screenshot_20211217-084404.png

With the result being:

ice_screenshot_20211217-084411.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 17, 2021 Dec 17, 2021

Copy link to clipboard

Copied

Thank you. Have a nice weekend!

Your script is very good, but I want to implement this function based on this script. Is it feasible?

How to do a wildcard / GREP / regex find-replace in Illustrator? - Graphic Design Stack Exchange

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 19, 2021 Dec 19, 2021

Copy link to clipboard

Copied

I tend to over-complicate things so you may want a simpler solution, but if I were to rewrite the function you've shown me I would do it like this:

 

var options = {
  // Bypass all find/replace prompts, just remove the newlines:
  removeNewlines: false,
  //
  find: {
    value: "[\\r\\n\\cC]", // Text to appear as default
    title: "Find:", // Title of window
    desc: "Enter RegExp/GREP/Text", // Description of window
    flags: "gm",
  },
  replace: {
    value: "",
    title: "Replace:",
    desc: "Enter Text",
  },
  confirm: {
    value: false,
    title: "Enable line-splitting?",
    desc: "Choose no to enable global flags and newline targeting",
  },
  lineSplitting: {
    onSplit: /[\r\n\cC]/gm, // RegExp to use for manual newline split
    onJoin: "\r\n", // Value to join newlines back with
  },
  showChanges: true, // Whether to display alert on completion noting change count
};

Array.prototype.filter = function(callback) {
  var filtered = [];
  for (var i = 0; i < this.length; i++)
    if (callback(this[i], i, this)) filtered.push(this[i]);
  return filtered;
};

function get(type, parent) {
  if (arguments.length == 1 || !parent) parent = app.activeDocument;
  var result = [];
  if (!parent[type]) return result;
  for (var i = 0; i < parent[type].length; i++) result.push(parent[type][i]);
  return result;
}

function findReplace() {
  try {
    var doc = app.activeDocument,
      scope = doc.selection.length
        ? get("selection").filter(function(i) {
            return i.typename == "TextFrame";
          })
        : doc.textFrames,
      count = 0;
    if (options.removeNewlines) {
      for (var i = 0; i < scope.length; i++) {
        var content = scope[i].contents;
        var lines = content.split(/[\r\n\cC]/gm),
          newStr = [];
        for (var e = 0; e < lines.length; e++)
          newStr.push(lines[e].replace(find, replace));
        scope[i].contents = newStr.join(" ").replace(/\s{2,}/gm, "");
      }
      return null;
    }
    var find = prompt(
      options.find.desc,
      options.find.value,
      options.find.title
    );
    if (find !== null) {
      var findRX = new RegExp(find, options.find.flags),
        shouldSplit = confirm(
          options.confirm.desc,
          !options.confirm.value,
          options.confirm.title
        );
      var replace = prompt(
        options.replace.desc,
        options.replace.value,
        options.replace.title
      );
      if (replace !== null) {
        for (var i = 0; i < scope.length; i++) {
          var content = scope[i].contents;
          if (shouldSplit) {
            var lines = content.split(options.lineSplitting.onSplit),
              newStr = [];
            for (var e = 0; e < lines.length; e++) {
              if (findRX.test(lines[e])) count++;
              newStr.push(lines[e].replace(findRX, replace));
            }
            scope[i].contents = newStr.join(options.lineSplitting.onJoin);
          } else {
            if (findRX.test(scope[i].contents)) count++;
            scope[i].contents = scope[i].contents.replace(findRX, replace);
          }
        }
        if (options.showChanges) {
          var alertStr = !count
            ? "No changes made"
            : count > 1
            ? count + " changes made"
            : "1 change made";
          alert(alertStr);
        }
      }
    }
  } catch (err) {
    alert("Error: " + err);
  }
}
findReplace();

 

With options.removeNewLines set, there is no UI. It just takes this:

ice_screenshot_20211219-093500.png

And turns it into this:

ice_screenshot_20211219-093505.png

 

Otherwise all the option values at the top of the script determine the behavior and UI:

ice_screenshot_20211219-093646.png

ice_screenshot_20211219-093701.png
The above defaults to No, which targets the "paragraph" and all lines for a single RegExp replace. When choosing Yes, it will split each line into a sentence and run an individual replace on each sentence, then reconstruct and assign the value back to the original TextFrame. All this behavior is configurable through the options object at the top of the script.

 

ice_screenshot_20211219-093710.png

ice_screenshot_20211219-093719.png

ice_screenshot_20211219-093727.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Dec 19, 2021 Dec 19, 2021

Copy link to clipboard

Copied

LATEST

Thank you! Your script solved all my problems perfectly.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines