I have the code bellow to find the regular expression after %hostname and it replaces all the text correrctly for #hostname.
How do I replicate this for %Location and #Location. I can't seem to get the replication working for more than one variable.
Thanks
var host= "%hostname =(.*)"; // Perl regular expression to find title string
UltraEdit.activeDocument.top();
// Turn on regular expressions
UltraEdit.activeDocument.findReplace.regExp = true;
// Find it
UltraEdit.activeDocument.findReplace.find(host);
// Load it into a selection
var host2= UltraEdit.activeDocument.selection;
// Javascript function 'match' will match the regex within the javascript engine
// so we can extract the actual title via array
t = host2.match(host);
savehost = t[1];
UltraEdit.activeDocument.top();
UltraEdit.activeDocument.findReplace.replaceAll=true;
UltraEdit.activeDocument.findReplace.matchCase=true;
UltraEdit.activeDocument.findReplace.replace("#hostname", savehost);
Here is the UltraEdit script for this task.
The array asVariables contains the names of the variables which can be extended by you with additional strings.
if (UltraEdit.document.length > 0) // Is any file opened?
{
// Define environment for this script.
UltraEdit.insertMode();
UltraEdit.columnModeOff();
// Define a constant array of variable names which can be extended
// or modified in script code at any time to support more variables.
var asVariables = [ "hostname" , "Location" ];
// Define once all find and replace options to make the
// script independent on internal defaults of UltraEdit.
UltraEdit.perlReOn();
UltraEdit.activeDocument.findReplace.mode=0;
UltraEdit.activeDocument.findReplace.matchCase=true;
UltraEdit.activeDocument.findReplace.matchWord=false;
UltraEdit.activeDocument.findReplace.searchDown=true;
if (typeof(UltraEdit.activeDocument.findReplace.searchInColumn) == "boolean")
{
UltraEdit.activeDocument.findReplace.searchInColumn=false;
}
UltraEdit.activeDocument.findReplace.preserveCase=false;
UltraEdit.activeDocument.findReplace.replaceAll=true;
UltraEdit.activeDocument.findReplace.replaceInAllOpen=false;
// Run the code in the loop on all variables defined in the array.
for (var nVariable = 0; nVariable < asVariables.length; nVariable++)
{
// Move caret to top of the active file.
UltraEdit.activeDocument.top();
// Perl regular expression to find %variable string and assigned data.
var sSearch = "%" + asVariables[nVariable] + " *?=.*$";
UltraEdit.activeDocument.findReplace.regExp=true;
// If the variable is not found in active file,
// continue immediately with next variable.
if(!UltraEdit.activeDocument.findReplace.find(sSearch)) continue;
// Get just the string after the first equal sign from selected string.
// The replace method of JavaScript String object never modifies the
// string value itself. It creates always a new string derived from
// the current string value with the replace applied.
var sData = UltraEdit.activeDocument.selection.replace(/^.*?=(.*)$/,"$1");
// Replace all occurrences of #variable by the found data in entire file.
UltraEdit.activeDocument.top();
UltraEdit.activeDocument.findReplace.regExp=false;
sSearch = "#" + asVariables[nVariable];
UltraEdit.activeDocument.findReplace.replace(sSearch,sData);
}
}
Related
Here is the code for a small syntax highlighter I made. It's supposed to search through every code tag in my .html file and make highlights to certain parts of it. Once this runs in the browser, I get this weird "keyword"> text in front of every line I have a keyword in. After some debugging, I still haven't came across a solution or a reason to why this problem occurs. I did notice that when I removed the ids from the code tag, the "keyword"> disappears, but the text still doesn't get highlighted.
If I code everything manually rather than using JavaScript to do it for me, everything works fine, but the problem is that the process is very time consuming and I have many more code snippets to do this for. Is there any way that I can get the matching keyword from keywords and include it in somehow? Is there a way to iterate over regular expressions like in arrays? Thanks in advance :)
image 1 (partial success):
I had to manually add span tags (removed unwanted text), but then highlighting doesn't work
image 2 (error image):
CSS code (inline)
.keyword {color: #c792ed;}
.identifier {color: #a6acce;}
.string {color: #6401e5;}
.int {color: #f78c6a;}
.comment {color: #69aa00;}
/*
#code0, #code1
^-----> ^-----> not defined
*/
Html code
<p>
<code id="code0">
let text = "I'd like 2 pizzas please"; // This is a string. It holds text characters
</code>
<br>
<code id="code1">
let ovenOn = true; // This is a Boolean. Its values are either 'true' or 'false'.
</code>
</p>
JavaScript code (inline)
let d = document;
let i = 0;
//----------------> Defining variables
function highlight() {
let tags = d.getElementsByTagName("code");
let reserved = "abstract arguments await boolean break byte case catch char class const continue debugger default delete do double else enum eval export extends false final finally float for function goto if implements import in instanceof int interface let long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var void volatile while with yield";
for(i; i<tags.length; i++){
let code = tags[i].innerHTML;
let keywords = new RegExp(reserved.split(' ').join('|'));
// ^------- keywords = ["abstract", "await", "etc..."]
// ^------- then becomes: keywords = /abstract|await|etc.../
code = code.replace(keywords, '<span class="keyword">$1</span>');
// ^---> Should capture the keyword in keywords (fails)
// ^---> see image2
code = code.replace(/"(.*?)"/g, '<span class="string">"$1"</span>');
// ^---> captures strings and places contents between quotes (works)
code = code.replace(/\/\/(.*)/g,'<span class="comment">// $1 </span>');
// ^---> captures single-line comments (works)
tags[i].innerHTML = code;
}
}
window.addEventListener('load', highlight);
// ^-----> Calling highlight();
I fixed some things in the function.
function highlight() {
let tags = d.getElementsByTagName("code");
// I moved the reserved and keyword variables out the for loop so it will not be reinitialized for every code element
// Its best to wrap the reserved words in word boundaries so if the reserved word is inside another word, it won't get replaced.
// Example: 'with' as a reserved word will affect 'without'
let reserved = "\\b(abstract arguments await Boolean break byte case catch char class const continue debugger default delete do double else enum eval export extends false final finally float for function goto if implements import in instanceof int interface let long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var void volatile while with yield)\\b";
//'I passed a global flag to the RegExp so all occurences of a reserved word will be replaced'
const keywords = new RegExp(reserved.split(' ').join('|'), 'g');
// The for loop doesn't run because i wasn't initialized.
for (let i = 0; i < tags.length; i++) {
let code = tags[i];
code = code.replace(keywords, `<span class="keyword">$&</span>`);
// After it the matches and replaces the reserved word, the class of the span tag is wrapped in quotes, so i fixed the regex to skip any match that is wrapped in the html tags <>
code = code.replace(/(?!.*>)"(.*?)"/g, '<span class="string">"$1"</span>');
code = code.replace(/\/\/(.*)/g, '<span class="comment">// $1 </span>');
tags[i].innerHTML = code;
}
}
// One of your examples should return this.
// <span class="keyword">let</span> text = <span class="string">"I'd like 2 pizzas please"</span>; <span class="comment">// This is a string. It holds text characters</span>
I think the problem is in how you are writing the HTML string. If you use a template literal (backtick) instead of quotes I think you get the functionality you need.
Here's an example which I think works?
let reserved =
'abstract arguments await boolean'; // have simplified
const keywords = new RegExp(reserved.split(' ').join('|'));
const sample = `<code>let a = new boolean(true);</code>`;
const example = `<span class="keyword">$1</span>`;
console.log(sample.replace(keywords, example));
/* Returns:
<code>
let a = new <span class="keyword">$1</span>(true);
</code>
*/
I'm working on my final project of the Winter 2017 quarter to demonstrate how to use Regular Expressions in both C# and JavaScript code behind pages. I've got the C# version of my demonstration program done, but the JavaScript version is making me pull what little hair I have left on my head out (no small achievement since I got a fresh buzz cut this morning!). The problem involves not getting any output after applying a Regular Expression in a While loop to get each instance of the expression and printing it out.
On my HTML page I have an input textarea, seven radio buttons, an output textarea, and two buttons underneath (one button is to move the output text to the input area to perform multiple iterations of applying expressions, and the other button to clear all textareas for starting from scratch). Each radio button links to a function that applies a regular expression to the text in the input area. Five of my seven functions work; the sixth is the one I can't figure out, and the seventh is essentially the same but with a slightly different RegEx pattern, so if I fix the sixth function, the seventh function will be a snap.
(I tried to insert/upload a JPG of the front end, but the photo upload doesn't seem to be working. Hopefully you get the drift of what I've set up.)
Here are my problem children from my JS code behind:
// RegEx_Demo_JS.js - code behind for RegEx_Demo_JS
var inputString; // Global variable for the input from the input text box.
var pattern; // Global variable for the regular expression.
var result; // Global variable for the result of applying the regular expression to the user input.
// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
function StringBuilder()
{
var strings = [];
this.append = function (string)
{
string = verify(string);
if (string.length > 0) strings[strings.length] = string;
}
this.appendLine = function (string)
{
string = verify(string);
if (this.isEmpty())
{
if (string.length > 0) strings[strings.length] = string;
else return;
}
else strings[strings.length] = string.length > 0 ? "\r\n" + string : "\r\n";
}
this.clear = function () { strings = []; };
this.isEmpty = function () { return strings.length == 0; };
this.toString = function () { return strings.join(""); };
var verify = function (string)
{
if (!defined(string)) return "";
if (getType(string) != getType(new String())) return String(string);
return string;
}
var defined = function (el)
{
// Changed per Ryan O'Hara's comment:
return el != null && typeof(el) != "undefined";
}
var getType = function (instance)
{
if (!defined(instance.constructor)) throw Error("Unexpected object type");
var type = String(instance.constructor).match(/function\s+(\w+)/);
return defined(type) ? type[1] : "undefined";
}
}
Within the code of the second radio button (which will be the seventh and last function to complete), I tested the ScriptBuilder with data in a local variable, and it ran successfully and produced output into the output textarea. But I get no output from this next function that invokes a While loop:
function RegEx_Match_TheOnly_AllInstances()
{
inputString = document.getElementById("txtUserInput").value;
pattern = /(\s+the\s+)/ig; // Using an Flag (/i) to select either lowercase or uppercase version. Finds first occurrence either as a standalone word or inside a word.
//result = pattern.exec(inputString); // Finds the first index location
var arrResult; // Array for the results of the search.
var sb = getStringBuilder(); // Variable to hold iterations of the result and the text
while ((arrResult = pattern.exec(inputString)) !==null)
{
sb.appendLine = "Match: " + arrResult[0] ;
}
document.getElementById("txtRegExOutput").value = sb.toString();
/* Original code from C# version:
// string pattern = #"\s+(?i)the\s+"; // Same as above, but using Option construct for case insensitive search.
string pattern = #"(^|\s+)(?i)the(\W|\s+)";
MatchCollection matches = Regex.Matches(userTextInput, pattern);
StringBuilder outputString = new StringBuilder();
foreach (Match match in matches)
{
string outputRegExs = "Match: " + "\"" + match.Value + "\"" + " at index [" + match.Index + ","
+ (match.Index + match.Length) + "]" + "\n";
outputString.Append(outputRegExs);
}
txtRegExOutput.Text = outputString.ToString();
*/
} // End RegEx_Match_The_AllInstances
I left the commented code in to show what I had used in the C# code behind version to illustrate what I'm trying to accomplish.
The test input/string I used for this function is:
Don’t go there. If you want to be the Man, you have to beat The Man.
That should return two hits. Ideally, I want it to show the word that it found and the index where it found the word, but at this point I'd be happy to just get some output showing every instance it found, and then build on that with the index and possibly the lastIndex.
So, is my problem in my While loop, the way I'm applying the StringBuilder, or a combination of the two? I know the StringBuilder code works, at least when not being used in a loop and using some test data from the site I found that code. And the code for simply finding the first instance of "the" as a standalone or inside another word does work and returns output, but that doesn't use a loop.
I've looked through Stack Overflow and several other JavaScript websites for inspiration, but nothing I've tried so far has worked. I appreciate any help anyone can provide! (If you need me to post any other code, please advise and I'll be happy to oblige.)
I'm getting the following error in my app's script when replacing strings in a template file to generate reports.
Index (-1) value must be greater or equal to zero.
The function is listed bellow.
/**
* Search a String in the document and replaces it with the generated newString, and sets it Bold
*/
function replaceString(doc, String, newString) {
var ps = doc.getParagraphs();
for(var i=0; i<ps.length; i++) {
var p = ps[i];
var text = p.getText();
//var text = p.editAsText();
if(text.indexOf(String) >= 0) {
//look if the String is present in the current paragraph
//p.editAsText().setFontFamily(b, c, DocumentApp.FontFamily.COMIC_SANS_MS);
p.editAsText().replaceText(String, newString);
// we calculte the length of the string to modify, making sure that is trated like a string and not another ind of object.
var newStringLength = newString.toString().length;
// if a string has been replaced with a NON empty space, it sets the new string to Bold,
Logger.log([newString,newStringLength]);
if (newStringLength > 0) {
// re-populate the text variable with the updated content of the paragraph
text = p.getText();
Logger.log(text);
p.editAsText().setBold(text.indexOf(newString), text.indexOf(newString) + newStringLength - 1, true);
}
}
}
}
When it errors out
[newString,newStringLength] = [ The Rev Levels are at ZGS 003 on the electric quality standard. The part has a current change to ZGS 005!,108]
Does anyone have any suggestions?
Thanks in advance,
Michael
You are not handling the case where the string isnt there. Thus indexOf returns -1 and you use that. Also dont use reserved words like String for variable names.
Aanval op Vlemis (499|453) C44
This is what the string looks like. Though it's actually like this: "Aanval op variable (variable) variable
What I want to do is 1: get the coordinates (I already have this), 2 get Vlemis (first variable), get C44 (third variable) and check to see if the string is of this type.
My code:
$("#commands_table tr.nowrap").each(function(){
var text = $(this).find("input[id*='editInput']").val();
var attackername= text.match(/(?=op)[\s|\w]*(?=\()/);
var coordinates = text.match(/\(\d{1,3}\|\d{1,3}\)/);
});
Coordinates works, attackername however doesn't.
Html:
<span id="labelText[6]">Aanval op Vlemis (499|453) C44</span>
You should use one regex to take everything :
var parts = text.match(/(\w+)\s*\((\d+)\|(\d+)\)\s*(\w+)/).slice(1);
This builds
["Vlemis", "499", "453", "C44"]
If you're not sure the string is valid, test like this :
var parts = text.match(/(\w+)\s*\((\d+)\|(\d+)\)\s*(\w+)/);
if (parts) {
parts = parts.slice(1);
// do things with parts
} else {
// no match, yell at the user
}
For a client's requirement, I have set out several images as follows:
img/img1.jpg
img/img2.jpg
img/img3.jpg
...
img/img4.jpg.
Now, I need to make the function that loads images dynamic. At the moment, the current solution is as follows:
// Grab the last image path
var lastImagePath = $("lastImage").attr("src");
// Increment the value.
var nextImagePath = "img/img" + (+lastImagePath.replace("img/img").replace(".jpg") + 1) + ".jpg";
// So on.
I was wondering if there's a cleaner way to increment the number?
Slightly cleaner:
var nextImagePath = lastImagePath.replace(/\d+/, function (n) { return ++n; });
This uses the version of replace that accepts a regular expression and a function.