I'm trying to replace line breaks with "," to every line end up like this 85aacb80-bh00-40e3-813c-5ad62ee93f42,324234,user#gmail.com
And make sure of the format, the long numbers and letters to be always the 1st, the id "324234" to be the second and email field to be always at 3rd. If some line is not matching the order go get deleted and be writed into another output file.
Though I'm stuck here It doesn't work..
The content of the txt file is this
85aacb80-bh00-40e3-813c-5ad62ee93f42
324234
usernine#gmail.com
And this is the code I'm trying
var neek = require('neek');
var readable = 'messagematch.txt';
var writable = 'outputmessagematch.txt';
neek.unique(readable, writable, function(result){ \\Here I remove duplicate lines
console.log(result);
});
const replace = require('replace-in-file');
const options = {
files: 'outputmessagematch.txt',
from: '\n',
to: ',',
};
Related
I have some tasks to handle in my daily jobs, so I need to do it in a automatic way. My task is:
there will be some messages sent to my IM, and I need to append the first, second & third number to each links with a "|".
if there only 2 numbers in the number line, a 0 is needed in the first place.
For example, in the cleanResult example, I need it to be done like:
finalResult = ["https://www.example.com/firstlink|500",
"https://www.example.com/firstlink|150",
"https://www.example.com/firstlink|30",
"https://www.exmaple.com/secondlink|600",
"https://www.exmaple.com/secondlink|150",
"https://www.exmaple.com/secondlink|30",
"https://www.example.com/thirdlink|500",
"https://www.example.com/thirdlink|150",
"https://www.example.com/thirdlink|30",
"https://www.example.com/forthlink|600",
"https://www.example.com/forthlink|100",
"https://www.example.com/forthlink|20",
"https://www.example.com/fithlink|0",
"https://www.example.com/fithlink|200",
"https://www.example.com/fithlink|50"
]
Here's the codes I had done so far:
const urlRegex = /(https?\:\/\/)?([^\.\s]+)?[^\.\s]+\.[^\s]+/gi;
const digitRegex = /^(?=.*\d)[\d ]+$/;
cleanResult = ["https://www.example.com/firstlink",
"https://www.exmaple.com/secondlink",
"https://www.example.com/thirdlink",
"500 150 30",
"https://www.example.com/forthlink",
"600 100 20",
"https://www.example.com/fithlink",
"200 50"
]
cleanResult.forEach((item, index) => {
if (item.match(digitRegex)) {
//codes I don't know how to do...
}
})
Are elements in cleanResult always either a URL or a number? In that case, you could just check the first character of the string to see if it's a number (basically a non-url). If it's not a URL, then we know it's numbers, and we can do something with the URL, which should the the previous element:
// If it's a URL, we will store it here for future use
let currentURL = ''
cleanResult.forEach((item, index) => {
// Get the first character of this string
const first = item[0]
if (!Number.isInteger(first)) {
// This is NOT a number, so must be a URL,
// let's store it in our variable to use in the next loop
currentURL = item
} else {
// This IS a number, which means we need to do a few things:
// 1. Split into separate numbers
// 2. Create a new URL pattern from each number
// 3. Push to finalResult
// 1. Split by tab delimiter (?)
// splits by tab, and returns an array
const numbers = item.split('\t')
// 2. Create a new URL pattern from each number
numbers.forEach((n) {
// This should now give you the URL + | + the number:
// ex: https://example.com/firstlink|500
const newURL = currentURL + '|' + n
// 3. push to the finalResult array
finalResult.push(newURL)
})
}
})
I haven't tested it, but this is the process that I generally use: break it into smaller tasks and take it one step at a time. I also didn't use regex, just to make it easier. We're assuming that you will receive either a URL or a list of numbers separated by a tab. This means you can afford to keep it a bit simple.
I'm sure there are way more efficient ways to do it and in a lot fewer lines, but if you're just learning JS or programming, there is nothing wrong with being extra verbose so that you can understand early concepts.
I'm loading a tab delimited text file using the FileReader API. Once loaded I need to find the tab location in the first line, parse out the characters preceding the tab, do some stuff with the parsed characters, then proceed to the second line, parse out the characters before the first tab in the second line, do some stuff with the parsed characters, then proceed to the third line, and so on until the end of the file.
I'm not a coder. I could use some help on the script to perform these operations.
Update/Edit (as requested): Specifically, taking it step by step:
I'm able to load the tab delimited file.
I'm able to step through the lines of the file (row 15+).
I'm making progress on stepping through the lines in the file (row 15+).
But I'm failing in the ability to perform a set of tasks as each line is read.
As each line is read, I want to parse out the characters in the line that are prior to the first tab character. In the example file contents below, I want to parse out 5, then I wish to take action on the 5. After that I want to parse out 10, then take action on the 10. Then I want to parse out 200 and take action on the 200. Then the script will end.
I'm assuming as each line is read that I want to call another function and send the contents of the first line to the new function. The new function will then parse out the characters before the first tab. Is this correct? If not, then what should I be doing? After that I'm assuming I should call another function, which will take the action on the parsed characters. Is this correct (and if not, what should I be doing instead)?
If I'm correct that I should be calling another function with each line read, then how do I do so (including sending the contents of the line)? In the code shown, I've been unsuccessful in figuring out how to do this.
Thank you,
Andrew
Example of tab delimited file:
5 15:00:05 2 1
10 15:00:10 2 2
200 15:03:20 2 3
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function (e) {
// Entire file
fileDisplayArea.innerText = reader.result;
// Count of lines in file
var lines2 = reader.result.split("\n").length;
fileDisplayArea2.innerText = "The number of lines in the text file is: " + Number(lines2-1);
// Attempt at an action per line
var lines = reader.result.split('\n');
for (var line = 0; line < lines.length; line++) {
//console.log(lines[line])
//with each line, how can I call another function and send along with the call the contents of the line?
fileDisplayArea3.innerText = lines;
}
}
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!"
}
});
Select a text file:
<input type="file" id="fileInput">
<hr />
<pre id="fileDisplayArea"></pre>
<hr />
<pre id="fileDisplayArea2"></pre>
<hr />
<pre id="fileDisplayArea3"></pre>
Here is an example of what you want to do. When looping each line you can get the text of that line with lines[line] from the lines array. You can then pass that text (and in my example the line number) to a function.
In my example the function is doStuff and it then splits the line text by tab character getting an array of "cells" (the values on the line that are delimited by tabs). I had the function output the values so that you could see them. You can have it do whatever you need.
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function (e) {
// Entire file
fileDisplayArea.innerText = reader.result;
// Count of lines in file
var lines2 = reader.result.split("\n").length;
fileDisplayArea2.innerText = "The number of lines in the text file is: " + Number(lines2);
// Attempt at an action per line
var lines = reader.result.split('\n');
for (var line = 0; line < lines.length; line++) {
doStuff(line, lines[line]);
fileDisplayArea3.innerText = lines;
}
}
reader.readAsText(file);
} else {
fileDisplayArea.innerText = "File not supported!"
}
});
function doStuff(lineNumber, lineText) {
// do something with the
var cells = lineText.split('\t'); // '\t' is a tab character
cellValues.innerText += "Line: " + (lineNumber + 1) + "\n";
cells.forEach(function(value) {
// do something with each "value" that was delimited by the "tab" characters
// in this example add the value to cellValues
// you can do whatever you want with the "value" here
cellValues.innerText += '\t' + value + '\n';
});
}
Select a text file:
<input type="file" id="fileInput">
<hr />
<pre id="fileDisplayArea"></pre>
<hr />
<pre id="fileDisplayArea2"></pre>
<hr />
<pre id="fileDisplayArea3"></pre>
<hr />
<pre id="cellValues"></pre>
Update: Explanation of doStuff
The first line of the function is var cells = lineText.split('\t'); This does not "replace" the tab characters with commas. What it does is create an array and store it into the cells variable.
In your original code the reason this line fileDisplayArea3.innerText = lines; is displayed with commas is because the lines array is transformed to a string in order to put it into innerText. Internally javascript calls the toString() method on the array which outputs it's elements separated by commas.
So continuing on. cells is now an array of the values of the line that were separated (delimited) by tab characters. We could use a for loop like you did to iterate the lines but I chose to use forEach. forEach will loop through (as the name suggests) each element of the array passing it's value to the function. The value is now available to do whatever we want with it i.e. make decisions, do math on it, etc... or (in my case) write it out to be seen.
Using node.js, I am trying to build an array of objects and write them to a file. To do this, I'm using the built in fs library.
After calling
var file = fs.createWriteStream('arrayOfObjects.json'); and file.write('[') I run several asynchronous functions to eventually append objects like this:
file.write(JSON.stringify(objectToAppend) + ',\n')
I can determine when all of the objects have stopped appending, and this is where I run file.write(']') and file.end(). My problem is that adding the last comma to the end of the last object causes the JSON to be invalid.
It is very difficult to determine where and when the last object is being created due to the asynchronous nature of the script, so I was wondering if there is a way to strip or remove characters from a file-stream. If so, I could do this before adding the last ']' character.
I could do this manually, but I was hoping to pipe this to another application. The only solution I've thought about is using the fs.truncate() function, however this doesn't seem to work for file streams, and neither file.length or file.length() will give me the length of the contents because it is not a string so it's difficult to determine how or where to truncate the file.
For now I have just been adding '{}]' to the end of the array to make it valid JSON, but this empty object may cause some problems later.
Also note: the array of objects I am writing in this stream is VERY large, so I would rather not end the stream and re-open the file.
I'd recommend to prepend the separator instead, so that you dynamically can adjust it after the first call:
file.write('[\n')
var sep = "";
forEach(function(objectToAppen) {
file.write(sep + JSON.stringify(objectToAppend))
if (!sep)
sep = ",\n";
});
Example using JSONStream:
var JSONStream = require('JSONStream');
var fs = require('fs');
var jsonwriter = JSONStream.stringify();
var file = fs.createWriteStream('arrayOfObjects.json');
// Pipe the JSON data to the file.
jsonwriter.pipe(file);
// Write your objects to the JSON stream.
jsonwriter.write({ foo : 'bar#1' });
jsonwriter.write({ foo : 'bar#2' });
jsonwriter.write({ foo : 'bar#3' });
jsonwriter.write({ foo : 'bar#4' });
// When you're done, end it.
jsonwriter.end();
Here's a snippet incorporating robertklep's answer. This converts from a pipe-separated file to json:
var fs = require('fs');
var readline = require('readline');
var JSONStream = require('JSONStream');
// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
console.log('Usage: node ' + process.argv[1] + ' FILENAME');
process.exit(1);
}
var filename = process.argv[2];
var outputFilename = filename + '.json';
console.log("Converting psv to json. Please wait.");
var jsonwriter = JSONStream.stringify();
var outputFile = fs.createWriteStream(outputFilename);
jsonwriter.pipe(outputFile);
var rl = readline.createInterface({
input: fs.createReadStream(filename),
terminal: false
}).on('line', function(line) {
console.log('Line: ' + line);
if(!/ADDRESS_DETAIL_PID/.test(line))
{
var split = line.split('|');
var line_as_json = { "address_detail_pid": split[0], "flat_type": split[1], "flat_number": split[2], "level_type": split[3], "level_number": split[4], "number_first": split[5], "street_name": split[6], "street_type_code": split[7], "locality_name": split[8], "state_abbreviation": split[9], "postcode": split[10], "longitude": split[11], "latitude": split[12] };
jsonwriter.write(line_as_json);
}
}).on('close', () => {
jsonwriter.end();
});;
console.log('psv2json complete.');
The accepted answer is interesting (prepending the separator) but in my case I have found it easier to append the separator and remove the last character of the file, just as suggested in the question.
This is how you remove the last character of a file with Node.js :
import fs from 'fs'
async function removeLastCharacter(filename) {
const stat = await fs.promises.stat(filename)
const fileSize = stat.size
await fs.promises.truncate(filename, fileSize - 1)
}
explanation :
fs.promises.stat gives us some information about the file, we will use its size.
fs.promises.truncate remove from the file what is after a certain position
We use the position fileSize - 1 which is the last character.
Note :
Yes I know that we need to wait until the stream is closed, but this is ok because truncate and stat functions are very fast and doesn't depend on the file size, it doesn't have to read its content.
Is it possible to get the filename without the extension from the src filepath.
As an example, let's say the src file is my-file.png - located at images/my-file.png.
In my task I have this at the moment:
var processName = options.processName || function (name) { return name; };
var filename = processName(filepath);
When I reference filename for output it returns:
images/my-file.png
I want to only return the actual filename, without the path and without the extension:
my-file.png
How can I achieve this?
Might be pretty old but if someone else finds this SO., in reply for #user3143218 's comment :
slice(0, -4) will remove the last 4 characters from the name, so for the example my-file.png we will get my-file but for script.js we will get scrip. I suggest using a regex removing everything from the last dot.
You could use a regex like this:
var theFile = filename.match(/\/([^/]*)$/)[1];
var onlyName = theFile.substr(0, theFile.lastIndexOf('.')) || theFile;
That should give you my-file. The regex gives you the string after the last forward slash, and the next line removes everything after the last dot (and the dot).
Thanks to Andeersg's answer below I was able to pull this off. It might not be the best solution but it works. Final code is:
var processName = options.processName || function (name) { return name; };
var filename = processName(filepath);
var theFile = filename.match(/\/([^/]*)$/)[1];
var onlyName = theFile.slice(0, -4);
Now onlyName will return:
my-file
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
}