I have a problem with replacing all the occurences of a slash inside my string to a double-slash. Right now this problem is preventing me from opening a file, thus I need to "escape" all the slashes in my path.
The path looks something like this:
C:\Folder\tmp\c235adf5b8c79ee61910a0c04abf9bc1
I want to replace all the slashes to double slashes, so that in the end it would look like this:
C:\\Folder\\tmp\\c235adf5b8c79ee61910a0c04abf9bc1
I already tried using this solution but it doesn't work for me:
str.replace(/\\/g, "\\\\");
The output of the solution above produces the following string:
C:Folder mpc235adf5b8c79ee61910a0c04abf9bc1
EDIT This is the actual code where I'm trying to solve the problem:
exports.register = function (req, res) {
let user = new db.User();
req.files.forEach(function(file) {
const uploadDir = 'upload/' + user._id + '/' + file.name;
const filePath = path.resolve('./' + file.path);
console.log(filePath);
ftp.put(filePath, uploadDir, function(err) {
if(err) return console.log(err);
console.log('Uploaded file: ' + file.name);
});
});
};
I omitted irrelevant parts
The \ character is an escape character in a JavaScript string literal. It doesn't exist in the string.
You can't use a regular expression to fix your problem because it is the source code you need to change, not the data in the string itself.
By the time you get the string, the \ characters will have been parsed and (for example) \t turned into a tab. At this point it is too late to manipulate the data to get the actual directory path back.
If your input is hard coded in your JavaScript, then your escaping the characters in that string unless you escape the escape characters (\\). Try just a console output of that string as you have it
console.log('C:\Folder\tmp\c235adf5b8c79ee61910a0c04abf9bc1');
// outputs "C:Folder mpc235adf5b8c79ee61910a0c04abf9bc1"
So the replacement for the slashes isn't replacing anything because there isn't actually any slashes in it.
'C:\\Folder\\tmp\\c235adf5b8c79ee61910a0c04abf9bc1'.replace(/\\/g, '\\\\')
Running something like that above outputs exactly what you're looking for.
To elaborate a bit, that gap between C:Folder and mpc235adf5b8c79ee61910a0c04abf9bc1 is there because \t is the tab character, and that space is a tab. The c is still there after mp because \c isn't anything, it's not an escape sequence.
If you got this text from a different source (not hard coded in the JS), then you wouldn't need to worry about this and your str.replace(/\\/g, "\\\\"); would work as expected.
var Path = 'C:\\Folder\\tmp\\c235adf5b8c79ee61910a0c04abf9bc1';
console.log(Path);
console.log(Path.replace(/\\/g, '\\\\'))
console.log(Path.replace(/\\/g, '/'))
//VM2431:2 C:\Folder\tmp\c235adf5b8c79ee61910a0c04abf9bc1
//VM2431:3 C:\\Folder\\tmp\\c235adf5b8c79ee61910a0c04abf9bc1
//VM2431:4 C:/Folder/tmp/c235adf5b8c79ee61910a0c04abf9bc1
Use String#raw.
String.raw`C:\Folder\tmp\c235adf5b8c79ee61910a0c04abf9bc1`
Output:
"C:\\Folder\\tmp\\c235adf5b8c79ee61910a0c04abf9bc1"
Related
I am hoping to get some insight into this issue I am having. I couldn't really find any other questions like this doing the same thing. I am using python 3.7.
I am pulling in contents of strings using regex which then will replace other parts of a JavaScript file I am reading in. I am familiar with raw strings when reading data in, but when I go to replace certain parts containing the double backslash only one is printed. I know it is escaping the string due to the backslash on the \", but I am at a loss with this. Adding a third "\" to it making it "\\\" will solve the issue, but I cannot do that due to the type of data I am working with.
For example, I want to replace all instances that the string "Ch" is found in a file I am reading in with "\\" using regex. This new data is then outputted to a new file.
How do I go about replacing certain content with the string '"\\"' ensuring that nothing is escaped and only "\\" is outputted?
Simplified sample code for testing:
string = R'"\\"'
Converted_Text = re.sub("Ch", ' ' + string, Converted_Text)
with open('output.js','w') as w:
w.write(Converted_Text.strip().replace('\n',''))
Sample file being read in:
var test = Ex("Temp") + Ch + wn;
var num1= 1;
var num2 =2;
var sum = num1+num2;
var blah, meh;
You can first replace CH with \\CH and again replace CH with \\.
This question already has an answer here:
Regular expression works on regex101.com, but not on prod
(1 answer)
Closed 2 years ago.
I want to get all the content in a text file before the first empty line.
I've found a working regex, but when I try to accomplish the same in Javascript it doesn't work.
(loading the file's contents is working)
async function readDir() {
return new Promise((resolve,reject) => {
fs.readdir('./content', (err, files) => {
if(err) { reject(err) }
resolve(files)
});
});
}
readDir().then((files) => {
files.forEach(file => {
var filepath = path.resolve('./content/'+file)
if(filepath.endsWith('.txt')) {
if(fs.statSync(filepath)["size"] > 0) {
let data = fs.readFileSync(filepath).toString();
let reg = /^[\s\S]*?(?=\n{2,})/;
console.log(data.match(reg)) //returns null
}
}
});
})
EDIT:
As O. Jones pointed out, the problem lies with the line endings. My regex was not picking up on \r\n line endings present in my file.
For now, this one seems to do the job: /^[\s\S]*?(?=(\r\n\r\n?|\n\n))/m
It looks like you want to match your re to the whole, multiline, contents of your file. You need the multiline flag to do that.
Try this
let reg = /^[\s\S]*?(?=\n{2,})/m;
Notice the m after the re's closing /. For more explanation see the section called Advanced Searching With Flags here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Also, it's possible you have line-ending trouble. Linux/ FreeBSD/ UNIX systems use \n aka newline to mark the end of each line. Macs use \r aka return for that. And Windows uses \r\n, two characters at the end of each line. Yeah, we all know what a pain in the xxx neck this is.
So your blank line detector is probably too simple. Regular Expression to match cross platform newline characters Try using this to match cross-os ends of lines
\r\n?|\n
meaning either a return followed by an optional newline, or just a newline.
It might look something like this.
let reg = /^[\s\S]*?(?=(\r\n?|\n)(\r\n?|\n))/m;
That looks for two of those end of line patterns in a row (not tested by me, sorry).
You may want to try:
const EOL = require('os').EOL; // system newline.
const regex = new Regex('^.*?(?=' + EOL + EOL + ')', 's'); // everything before first two newlines.
I am processing markdown files in my nodeJS application. So I have my markdown held as a string. I am trying to determine the difference between markdown like:
```Javascript
var code_block = something;
and
```
var code_block = something;
so I am approaching the issue like:
var language = markdown_string.substr(0, markdown_string.search("\n"));
console.log("Language: " + language);
So I am searching the string for the code between the ``` and the newline, however, the \n isn't being found, so the string represents the rest of the file. if I search for (blank space), then I get the var included, so my string doesn't seem to have anything detectable between the end of the backticks or the language and the next line.
Is this correct? Can you see any way I can pick up the rest of the top line after the triple backticks but before the var on the next line?
I have found that by splitting the string into chars, i.e. var chars = markdown.split(""); and then looping through the next 15 values until chars[i] equals \n and using that as an index to substring the necessary part of the string. It works, but is a bit messy ...
I'm doing some more advanced automation on iOS devices and simulators for an enterprise application. The automation is written in browserless Javascript. One of the methods works on the device but not on the simulator, so I need to code a workaround. For the curious, it's UIATarget.localTarget().frontMostApp().preferencesValueForKey(key).
What we need to do is read a path to a server (which varies) from a plist file on disk. As a workaround on the simulator, I've used the following lines to locate the plist file containing the preferences:
// Get the alias of the user who's logged in
var result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/whoami", [], 5).stdout;
// Remove the extra newline at the end of the alias we got
result = result.replace('\n',"");
// Find the location of the plist containing the server info
result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/find", ["/Users/"+result+"/Library/Application Support/iPhone Simulator", "-name", "redacted.plist"], 100);
// For some reason we need a delay here
UIATarget.localTarget().delay(.5);
// Results are returned in a single string separated by newline characters, so we can split it into an array
// This array contains all of the folders which have the plist file under the Simulator directory
var plistLocations = result.stdout.split("\n");
...
// For this example, let's just assume we want slot 0 here to save time
var plistBinaryLocation = plistLocations[0];
var plistXMLLocation = plistLocations[i] + ".xml";
result = UIATarget.localTarget().host().performTaskWithPathArgumentsTimeout("/usr/bin/plutil", ["-convert","xml1", plistBinaryLocation,"-o", plistXMLLocation], 100);
From here, I think the best way to get the contents is to cat or grep the file, since we can't read the file directly from disk. However, I'm having trouble getting the syntax down. Here's an edited snippet of the plist file I'm reading:
<key>server_url</key>
<string>http://pathToServer</string>
There are a bunch of key/string pairs in the file, where the server_url key is unique. Ideally I'd do something like a lookback, but because JavaScript doesn't appear to support it, I figured I'd just get the pair from the file and whittle it down a bit later.
I can search for the key with this:
// This line works
var expression = new RegExp(escapeRegExp("<key>server_url</key>"));
if(result.stdout.match(expression))
{
UIALogger.logMessage("FOUND IT!!!");
}
else
{
UIALogger.logMessage("NOPE :(");
}
Where the escapeRegExp method looks like this:
function escapeRegExp(str)
{
var result = str.replace(/([()[{*+.$^\\|?])/g, '\\$1');
UIALogger.logMessage("NEW STRING: " + result);
return result;
}
Also, this line returns a value (but gets the wrong line):
var expression = new RegExp(escapeRegExp("<string>(.*?)</string>"));
However, when you put the two together, it (the Regex syntax) works on the terminal but doesn't work in code:
var expression = new RegExp(escapeRegExp("<key>server_url</key>[\s]*<string>(.*?)</string>"));
What am I missing? I also tried grep and egrep without any luck.
There are two problems affecting you here getting the regex to work in your JavaScript code.
First, you are escaping the whole regex expression string, which means that your capturing (.*?) and your whitespace ignoring [\s]* will also be escaped and won't be evaluated the way you're expecting. You need to escape the XML parts and add in the regex parts without escaping them.
Second, the whitespace ignoring part, [\s]* is falling prey to JavaScript's normal string escaping rules. the "\s" is turning into "s" in the output. You need to escape that backslash with "\s" so that it stays as "\s" in the string that you pass to construct the regular expression.
I've built a working script that I've verified in the UI Automation engine itself. It should extract and print out the expected URL:
var testString = "" +
"<plistExample>\n" +
" <key>dont-find-me</key>\n" +
" <string>bad value</string>\n" +
" <key>server_url</key>\n" +
" <string>http://server_url</string>\n" +
"</plistExample>";
function escapeRegExp(str)
{
var result = str.replace(/([()[{*+.$^\\|?])/g, '\\$1');
UIALogger.logMessage("NEW STRING: " + result);
return result;
}
var strExp = escapeRegExp("<key>server_url</key>") + "[\\s]*" + escapeRegExp("<string>") + "(.*)" + escapeRegExp("</string>");
UIALogger.logMessage("Expression escaping only the xml parts:" + strExp);
var exp = new RegExp(strExp);
var match = testString.match(exp);
UIALogger.logMessage("Match: " + match[1]);
I should point out, though, that the only thing you need to escape in the regex is the forward slashes in the XML closing tags. That means that you don't need your escapeRegExp() function and can write the expression you want like this:
var exp = new RegExp("<key>server_url<\/key>[\\s]*<string>(.*)<\/string>");
Having this text:
http://img.oo.com.au/prod/CRWWBGFWG/1t44.jpg
And other texts like this where the last 1 can be any other number and the last 44 can be any other number as well, I need a regex that will match /1t44.jpg.
Everything I've tried so far (/.+?\.([^\.]+)$) matches from the first slash (//img.oo.com.au/prod/CRWWBGFWG/1t44.jpg).
I'm using JavaScript, so whatever works on RegexPal should do.
Here's a simple Regex that will match everything after the last /:
/[^/]*$
If you want to match a filename with a very specific file extenstion, you can use something like this:
/\/\dt\d\d\.jpg$/
This matches:
a slash
followed by a digit
followed by the letter 't'
followed by two digits
followed by '.jpg' at the end of the string
Or, if you really just want the filename (whatever is after the last slash with any file extension), then you can use this:
/\/[^\/]+$/
This matches:
a slash
followed by one or more non-slash characters
at the end of the string
In your sample string of http://img.oo.com.au/prod/CRWWBGFWG/1t44.jpg, both of these will match /1t44.jpg. The first is obviously much more restrictive since it requires a specific format of the filename. The second matches any filename.
Other choices. In node.js development, you can use the path module and use path.parse() to break a path up into all of its various components.
And, there are various libraries written for the browser that will break up a path into its components too.
As Johnsyweb says, a regular express isn't really needed here. AFAIK the fastest way to do this is with lastIndexOf and substr.
str.substr(str.lastIndexOf('/'));
Of course you don't have to use a regular expression to split a string and pop the last part:
var str="http://img.oo.com.au/prod/CRWWBGFWG/1t44.jpg";
var parts = str.split("/");
document.write(parts.pop() + "<br />");
Based on answer of Scott, try this: (JavaScript)
var url = "http://img.oo.com.au/prod/CRWWBGFWG/1t44.jpg";
var path = url.replace(/(.*)([\\\/][^\\\/]*$)/, "$1" );
var lastElement = url.replace(/(.*)([\\\/][^\\\/]*$)/, "$2" );
This can be also matched for Windows/Nix file path, to extract file name or file path :
c:\Program Files\test.js => c:\Program Files
c:\Program Files\test.js => \test.js
This is for Java on a Linux machine. It grabs the last part of a file path, so that it can be used for making a file lock.
// String to be scanned to find the pattern.
String pattern = ".*?([^/.]+)*$";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher match = r.matcher("/usr/local/java/bin/keystore");
/**
* Now you have two matches
* #0 /usr/local/java/bin/keystore
* #1 keystore
*/
String fileLock = "";
if (match.find()) {
fileLock = match.group(1) + ".lock";
}
A little different than the original question, I know. But I hope this helps others who were stuck with the same problem I had.