Line break every 3 executions [duplicate] - javascript

This question already has answers here:
Replace nth occurence of number in string with javascript [duplicate]
(2 answers)
Closed 3 years ago.
I have a code that replaces in a file all line breaks and sustitute for comma.
var fs = require('fs');
var str = fs.readFile('output.txt', 'utf-8', function(err, data) {
if (err) throw err;
console.log(data.replace(/\r\n/g, ','));
});
I'm trying to make a version that every 3 executions add a line break.
How I can accomplish this?

data.replace(/\n/g, ",").replace(/(([^,]*,){2}[^,]*),/g, '$1\n')
Or
data.replace(/\r\n/g, ",").replace(/(([^,]*,){2}[^,]*),/g, '$1\r\n')

String.prototype.replace can accept a replacer function as second argument, docs here. Using a function fits your case perfectly.
You can create a function that keeps an execution counter in its closure, then conditionally yields a line break on every 3 replacements.
function ReplacerFactory() {
var execCount = 0;
function replacer() {
execCount++;
if (execCount % 3) return ',';
return '\n';
}
return replacer;
}
console.log(data.replace(/\r\n/g, ReplacerFactory()));
var data = `a
quick
brown
fox
jumps
over
a
lazy
dog
yo!
`;
function ReplacerFactory() {
var execCount = 0;
function replacer() {
execCount++;
if (execCount % 3) return ',';
return '\n';
}
return replacer;
}
console.log(data.replace(/\n/g, ReplacerFactory()));

Related

Why is my way of extracting newlines from textarea working with \r [duplicate]

This question already has an answer here:
carriage return in textarea retrieved as line feed
(1 answer)
Closed 3 years ago.
If I set the value of a textarea to let's say "123456\r123" and call document.getElementById('myTextarea').value.indexOf("\n"), it returns 6, which is the position of the line break; but why is it not returning -1, as there is no \n inside the string?
I guess the browser auto transfer the '\r' to '\n' when you set value to the textarea.
When I run those codes in browser,the result told me what I guess is just the truth.
let textArea = document.getElementById("inputTextarea");
let value = "abcd\radc";
textArea.value = value;
let out = document.getElementById("outputPre");
document.getElementById("inputTextarea").addEventListener("click", () => {
value = textArea.value;
let chars = value.split("").map(s => s.charCodeAt(0));
let lf = ["\r".charCodeAt(0), "\n".charCodeAt(0)];
out.innerHTML = 'valueChars:<em>' + value.split("") + "</em><br/>ASCII:<em>" + chars.toString() + "</em>";
/*valueChars:a,b,c,d,
,a,d,c ASCII:97,98,99,100,10,97,100,99*/
console.info(lf); //13,10
});

.Trim Is Not A Function Error When Trying To Remove The Space From Returned Data [duplicate]

This question already has answers here:
Javascript - Apply trim function to each string in an array
(12 answers)
Closed 3 years ago.
I have a DataTable which is being populated by JSON. The days of the week (for example) are returning as a string which i am applying .split(',') to and is working in my forEach function, but i need to apply a class to my days returned buttons but due to the space in the string it only falls into my 'Mon' button and not the rest due to the space.
Working code
var selectedDays = modifyRecordData.selectedDays;
var splitSelectedDays = selectedDays.split(',');
console.log(splitSelectedDays);
splitSelectedDays.forEach(day => {
if(day == 'Mon') {
alert('in Mon')
$('#mon').removeClass('btn-default');
$('#mon').addClass('btn-primary');
}
if (day == 'Tue') {
alert('in Tue')
$('#tue').removeClass('btn-default');
$('#tue').addClass('btn-primary');
}
// AND SO ON
})
This also returns
I have tried the following but none are working
var selectedDays = modifyRecordData.selectedDays;
var splitSelectedDays = selectedDays.split(',').trim();
and
var selectedDays = modifyRecordData.selectedDays;
var splitSelectedDays = selectedDays.split(',').trim();
var test = splitSelectedDays.trim();
also thruught about trying in the actual loop as each one returned as a string using the below
splitSelectedDays.forEach(day => {
splitSelectedDays.trim();
But always get the function error.
I am wanting to remove the space, then lowercase the value then i can use the var in on addClass function rather than an IF for each day of the week
split in selectedDays.split(',').trim(); will create an array. There is no trim for array. So you can iterate the array and apply trim if it is a string
You can do like this
splitSelectedDays.forEach(day => {
let val = day.trim();
// rest of the code
})
var splitSelectedDays = selectedDays.split(',').trim();
This is your problematic line.
selectedDays.split(',') will return an array of strings. Trim is a method on a string, not an array of strings, that removes leading/trailing whitespace.
You will have to apply trim() to each individual element in the array.
For example
var splitSelectedDays = selectedDays.split(',');
for (var i=0; i < splitSelectedDays.length; i++)
{
splitSelectedDays[i] = splitSelectedDays[i].trim();
}

Unable to Get Output From While Loop in Javascript

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.)

my replace is not working in my function? [duplicate]

This question already has answers here:
How do I replace all occurrences of a string in JavaScript?
(78 answers)
Closed 8 years ago.
var jtj_code_lines = []; // this array will hold all the jtj codes line
var JTJ = function(j){
j = j.replace(" ","");
jtj_code_lines = j.split(';'); // splitting all the lines seperated from ;
for(var i=0; i<jtj_code_lines.length; i++){
if(jtj_code_lines[i].charAt(0) === '*'){ // * means that the following word is the name of a method that will perform some action
var q1 = jtj_code_lines[i].replace('*', ''),
q1_pos_1 = q1.indexOf('['); // find the position of the keyword [
var q1_funcname = q1.slice(0, q1_pos_1); // it find the name of that perticular function
if(q1_funcname === "Message"){ // this checks weather the function name is message
var q1_pos_2 = q1.indexOf(']'), // this ifnds the position of keyword ]
q1_func_value = q1.slice(q1_pos_1+1, q1_pos_2); // this finds what is written inside [] and accepts as the value of Message
alert(q1_func_value);
}else{
}
}
}
};
so the above function is pretty simple it finds the specific text written in the braces, i mean that if you write :
JTJ('*Message[hi];')
then it will alert hi and this is quit simple and this is alerting as expected but the problem is coming that if any * is after white space then that perticular thing is not being alerted, so the following have the same condition,*Message[go ]; starts with whitespace so it is not being alerted :
JTJ('*Message[sanmveg];*Message[saini]; *Message[go ];')
but i have a this line j = j.replace(" ",""); to remove all the white spaces, then why it is not working? is there any other way to do this?
thanks.
Fix: j = j.replace(/\s/gi,"");
this would remove all " " with "", in short it would act as replaceAll.
Before it was just replacing first matched " " with "".

How to generate call-graphs for given javascript? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I have seen "https://stackoverflow.com/questions/1385335/how-to-generate-function-call-graphs-for-javascript", and tried it. It works well, if you want to get an abstract syntax tree.
Unfortunately Closure Compiler only seems to offer --print_tree, --print_ast and --print_pass_graph. None of them are useful for me.
I want to see a chart of which function calls which other functions.
code2flow does exactly this. Full disclosure, I started this project
To run
$ code2flow source1.js source2.js -o out.gv
Then, open out.gv with graphviz
Edit: For now, this project is unmaintained. I would suggest trying out a different solution before using code2flow.
If you filter the output of closure --print_tree you get what you want.
For example take the following file:
var fib = function(n) {
if (n < 2) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
};
console.log(fib(fib(5)));
Filter the output of closure --print_tree
NAME fib 1
FUNCTION 1
CALL 5
NAME fib 5
SUB 5
NAME a 5
NUMBER 1.0 5
CALL 5
NAME fib 5
SUB 5
NAME a 5
NUMBER 2.0 5
EXPR_RESULT 9
CALL 9
GETPROP 9
NAME console 9
STRING log 9
CALL 9
CALL 9
NAME fib 9
CALL 9
CALL 9
NAME fib 9
NUMBER 5.0 9
And you can see all the call statements.
I wrote the following scripts to do this.
./call_tree
#! /usr/bin/env sh
function make_tree() {
closure --print_tree $1 | grep $1
}
function parse_tree() {
gawk -f parse_tree.awk
}
if [[ "$1" = "--tree" ]]; then
make_tree $2
else
make_tree $1 | parse_tree
fi
parse_tree.awk
BEGIN {
lines_c = 0
indent_width = 4
indent_offset = 0
string_offset = ""
calling = 0
call_indent = 0
}
{
sub(/\[source_file.*$/, "")
sub(/\[free_call.*$/, "")
}
/SCRIPT/ {
indent_offset = calculate_indent($0)
root_indent = indent_offset - 1
}
/FUNCTION/ {
pl = get_previous_line()
if (calculate_indent(pl) < calculate_indent($0))
print pl
print
}
{
lines_v[lines_c] = $0
lines_c += 1
}
{
indent = calculate_indent($0)
if (indent <= call_indent) {
calling = 0
}
if (calling) {
print
}
}
/CALL/ {
calling = 1
call_indent = calculate_indent($0)
print
}
/EXPR/{
line_indent = calculate_indent($0)
if (line_indent == root_indent) {
if ($0 !~ /(FUNCTION)/) {
print
}
}
}
function calculate_indent(line) {
match(line, /^ */)
return int(RLENGTH / indent_width) - indent_offset
}
function get_previous_line() {
return lines_v[lines_c - 1]
}
I finally managed this using UglifyJS2 and Dot/GraphViz, in a sort of combination of the above answer and the answers to the linked question.
The missing part, for me, was how to filter the parsed AST. It turns out that UglifyJS has the TreeWalker object, which basically applys a function to each node of the AST. This is the code I have so far:
//to be run using nodejs
var UglifyJS = require('uglify-js')
var fs = require('fs');
var util = require('util');
var file = 'path/to/file...';
//read in the code
var code = fs.readFileSync(file, "utf8");
//parse it to AST
var toplevel = UglifyJS.parse(code);
//open the output DOT file
var out = fs.openSync('path/to/output/file...', 'w');
//output the start of a directed graph in DOT notation
fs.writeSync(out, 'digraph test{\n');
//use a tree walker to examine each node
var walker = new UglifyJS.TreeWalker(function(node){
//check for function calls
if (node instanceof UglifyJS.AST_Call) {
if(node.expression.name !== undefined)
{
//find where the calling function is defined
var p = walker.find_parent(UglifyJS.AST_Defun);
if(p !== undefined)
{
//filter out unneccessary stuff, eg calls to external libraries or constructors
if(node.expression.name == "$" || node.expression.name == "Number" || node.expression.name =="Date")
{
//NOTE: $ is from jquery, and causes problems if it's in the DOT file.
//It's also very frequent, so even replacing it with a safe string
//results in a very cluttered graph
}
else
{
fs.writeSync(out, p.name.name);
fs.writeSync(out, " -> ");
fs.writeSync(out, node.expression.name);
fs.writeSync(out, "\n");
}
}
else
{
//it's a top level function
fs.writeSync(out, node.expression.name);
fs.writeSync(out, "\n");
}
}
}
if(node instanceof UglifyJS.AST_Defun)
{
//defined but not called
fs.writeSync(out, node.name.name);
fs.writeSync(out, "\n");
}
});
//analyse the AST
toplevel.walk(walker);
//finally, write out the closing bracket
fs.writeSync(out, '}');
I run it with node, and then put the output through
dot -Tpng -o graph_name.png dot_file_name.dot
Notes:
It gives a pretty basic graph - only black and white and no formatting.
It doesn't catch ajax at all, and presumably not stuff like eval or with either, as others have mentioned.
Also, as it stands it includes in the graph: functions called by other functions (and consequently functions that call other functions), functions that are called independantly, AND functions that are defined but not called.
As a result of all this, it may miss things that are relevant, or include things that are not. It's a start though, and appears to accomplish what I was after, and what led me to this question in the first place.
https://github.com/mishoo/UglifyJS
gives access to an ast in javascript.
ast.coffee
util = require 'util'
jsp = require('uglify-js').parser
orig_code = """
var a = function (x) {
return x * x;
};
function b (x) {
return a(x)
}
console.log(a(5));
console.log(b(5));
"""
ast = jsp.parse(orig_code)
console.log util.inspect ast, true, null, true

Categories