0

In nodejs is it possible to detect multiple occurrences of the same string in a txt file?

My current code is as below

const fs = require('fs');
var file_path = 'file.txt';
fs.readFile(file_path, "UTF-8", (error, data) => {
    if (error) throw error;
    else {
        if (data.includes('Test Value')) {
            console.log(data.indexOf('Test Value'))
        }
        fs.close(file, (err) => {
            if (err)
                console.error('Failed to close file', err);
            else {
                console.log("\n> File Closed successfully");
            }
        });
    }
});

In file.txt, I have below contents

Value1
Value2
Test Value
Value3
Test Value
Value4

when I run the above code, I could only detect first occurrence of 'Test Value' whereas I need to detect all occurrences of 'Test Value' in file.txt, please help

alex devassy
  • 437
  • 5
  • 17
  • `const lines = data.split('\n');` will give you an array of lines. You can now iterate over the array to check individual lines against 'Test Value' –  Apr 25 '22 at 08:09
  • I think you are finding the Readline function of nodejs. You need to take a look at https://stackoverflow.com/questions/6156501/read-a-file-one-line-at-a-time-in-node-js – deko_39 Apr 25 '22 at 08:19
  • @deko_39 readline works well for outputting the lines, but I would also need the offset value of "Test Value" in file.txt, I was hoping to use this offset value later for appending to the file – alex devassy Apr 25 '22 at 08:22
  • you can easily create another object to store all of those offset, for example: `const a = {}, let index =0, whenever a line is read, index++, if !a[''] => a[''] = [index] else a[''].push(index)` – deko_39 Apr 25 '22 at 08:30
  • `indexOf` has two parameters: `while ((pos = data.indexOf('Test Value', pos) >= -1)` – jabaa Apr 25 '22 at 08:30
  • the result will be something like: `a = {Value: [0,1,3,5], 'Test Value': [2,4]}` – deko_39 Apr 25 '22 at 08:31

4 Answers4

3

indexOf has two parameters. You can use store the last position and continue the next search at the next position:

const fs = require('fs');
var file_path = 'file.txt';
fs.readFile(file_path, "UTF-8", (error, data) => {
    if (error) throw error;
    else {
        
        for (let pos = data.indexOf('Test Value'); pos > -1; pos = data.indexOf('Test Value', pos + 1)) {
            console.log(pos);
        }
        fs.close(file, (err) => {
            if (err)
                console.error('Failed to close file', err);
            else {
                console.log("\n> File Closed successfully");
            }
        });
    }
});

Example:

const data = `Value1
Value2
Test Value
Value3
Test Value
Value4`;

for (let pos = data.indexOf('Test Value'); pos > -1; pos = data.indexOf('Test Value', pos + 1)) {
    console.log(pos);
}
jabaa
  • 5,844
  • 3
  • 9
  • 30
1

You can use a regexp global search (multiple matches) with the RegExp .exec() method.

A global search using the String .match() method returns just the matches without the index. However the RegExp .exec() method returns the index.

let match;
let search = /Test Value/g; // <-- the 'g' flag is important!

// If you need to construct the regexp dynamically
// do = new RegExp('Test Value', 'g')

while (match = search.exec(data)) {
    console.log(match.index);
}
slebetman
  • 109,858
  • 19
  • 140
  • 171
0

Yes. Loop through the data array and check each data element.

const fs = require('fs');
var file_path = 'file.txt';
fs.readFile(file_path, "UTF-8", (error, data) => {
    if (error) throw error;
    else {
        data.split('\n').forEach(line => {
            if (line === 'Test Value') {
                console.log(data.indexOf(line))
            }
        })
        fs.close(file, (err) => {
            if (err)
                console.error('Failed to close file', err);
            else {
                console.log("\n> File Closed successfully");
            }
        });
    }
});
timpa
  • 338
  • 1
  • 8
  • seems like foreach is not a function of data, getting below error `TypeError: data.forEach is not a function` – alex devassy Apr 25 '22 at 08:20
  • Ah, so data is of type String then. As "Chris G" mentioned, try converting `data` to an Array by replacing `data.forEach` with `data.split('\n').forEach`. – timpa Apr 25 '22 at 08:31
  • This prints two times `0`. Probably not very helpful in this case. – jabaa Apr 25 '22 at 08:55
-1

I used an array to store occurrences (line number) of a particular string in a file.

var linepos = [];
fs.readFile(file_name, "UTF-8", (error, data) => {
    if (error) throw error;
    else {
        let pos = 0;
        data.split(/\r?\n/).forEach(line => {
            if (line == 'Test Value') {
                //console.log(pos)
                linepos.push(pos);
            }
            pos = pos + 1
        });
    }
});

and then used this array to perform other operations such as append etc with foreach

linepos.forEach((item) => {
    //operations body
});
alex devassy
  • 437
  • 5
  • 17