Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find String in a Txt File, Delete Entire Line

I'm currently working with node.js to create an IRC bot. The bot allows users to add song links to a database. Each time someone submits a song, it is added to a new line of "shuffle.txt" as such:

user1,The Beatles,Yesterday,(youtube link)
user2,The Rolling Stones,Angie,(youtube link)
user1,The Bealtes,Yellow Sumbarine,(youtube link)

Notice that user1 mistyped some information in their latest addition. I'm trying to make an UNDO command so that a user can delete their most recently entered line. I plan on doing this by finding the latest occurrence of their name in shuffle.txt and deleting the entire line that it's found on. Here's my message listener:

bot.addListener('message', function(from, to, message) {
    if (message.indexOf(config.prefix) == 0) {

        message = message.slice(1);
        var token = message.split(" ");

        if (token[0] == 'undo') {
              //find and delete
            }

    }
});

the user entering the command is stored as from

I'm assuming I'll have to do something along the lines of this:

var songList = fs.readFileSync('shuffle.txt', 'utf8');
var position = songList.indexOf(from);

if (position != -1) { //if 'from' found

  //find LAST occurrence of 'from'
  //get length from here to next occurrence of '\n'
  //substr(length + 1)

  fs.writeFile('shuffle.txt', songList, function(err) {
    if (err) {
      console.log (err);
    }

}

I'm new to JavaScript and this is my first time using node.js so I can use any help I can get! Thanks everyone.

EDIT: I should also point out that I don't need help with the command recognition. I only need help with the finding/deleting portion. Cheers!

like image 912
Tyler Roper Avatar asked Apr 04 '14 09:04

Tyler Roper


2 Answers

Edit2: edited with a new solution.

You could try this:

fs.readFile('shuffle.txt', function read(err, data) {
    if (err) {
        throw err;
    }

    lastIndex = function(){
        for (var i = data_array.length - 1; i > -1; i--)
        if (data_array[i].match('user1'))
            return i;
    }()

    delete data_array[lastIndex];

});

Split file into lines, find the last line with a simple loop going backwards, remove the line using delete, then patch it back together.

demo

Also, you should not use readFileSync in node, as blocking node can be dangerous since it's single threaded.

like image 183
Mosho Avatar answered Sep 24 '22 02:09

Mosho


This seems to work ok. It's self contained so you can just paste into a HTML file to see it run. Basically keep running a regular expression to match the whole line starting with the username passed. The whole line is returned ("gm" part of regular expression tells it to match a line at a time) as a string.

Then you just to a replace of that returned line (as string) within the data. Note that this assumes that line is unique in the text file. If you think people might have entered the same line a few times (but only want to remove the last one) then the 'non lazy' option whcih I've left uncommented is best. I haven't tested what happens if the line is first in the data or last.

<html>
<head>
<script type="text/javascript">
var sData="user1,The Beatles,Yesterday,(youtube link)\nuser2,The Rolling Stones,Angie,(youtube link)\nuser1,The Bealtes,Yellow Sumbarine,(youtube link)\nuser3,The Rolling Stones,Angie,(youtube link)";

function replaceLastEntry(sText) {
  sNewData=sData;
  var re=new RegExp("^"+sText+".*$","gm"); // matches whole lines starting with sText 

  var lastIndex=-1;
  var i=0;
  var sMatch=re.exec(sData)!= null;
  while (sMatch!=null)
    {
    i++
    lastIndex=re.lastIndex;
    lastMatch=sMatch.toString(); // make note of last successful match - gives full line
    sMatch=re.exec(sData);
  }

  // at this point lastMatch contains the whole line which needs to be removed.
  // lastIndex is the string position of the character after the LAST string matched (ie the end of the matched line)
  // sNewData = sData.replace(lastMatch,""); // Lazy way - assumes the line is unique within the file

  // non-lazy way : locate the text by position returned and remove it
  sNewData = sData.substr(0, lastIndex-lastMatch.length-1) +   sData.substr(lastIndex);

  document.getElementById("Data").innerHTML=sData
  document.getElementById("NewData").innerHTML=sNewData
  document.getElementById("LastMatch").innerHTML=lastMatch
}

</script>
</head>


<body onload="replaceLastEntry('user1','newvalue')">
Data: <pre id="Data"></pre>
New Data:<pre id="NewData"></pre>
Last Match: <pre id="LastMatch"></pre>
</body>
</html>

hope this helps !

like image 35
user2808054 Avatar answered Sep 24 '22 02:09

user2808054