1

I have a string that contains names (firstname and lastname), username and email addresses of persons. I need to get the names and email addresses and add them into an HTML table using regex (regular expressions).

The HTML table should look like this:

enter image description here

This is my javascript code so far:

// this is some example of the names & email adresses - they are fake
const outlook = "Anders Jensen (EAAAANJE) <eaaaanje@students.eaax.dk>; Bodil Pedersen (EAAABOPE) <eaaabope@students.eaax.dk>; Åse Andersen (EAAAIDAN) <eaaaasan@students.eaax.dk>; Mühl Svendsen (EAAAPESV) <eaaamusv@students.eaax.dk>";

// we find all the emails & names of the students
let regexEmail = /\<.*?\>/g;
let regexName = /\w+\s\w+\s/gi;

// an array of all the td-tags
let tdTags = document.querySelectorAll("td");

// The emails and names are inserted in the table
for(let i = 0; regexName.exec(outlook) !== null; i++) {

    tdTags[i].innerHTML = regexName.exec(outlook)[i]; // name
    tdTags[i].nextSibling.innerHTML = regexEmail.exec(outlook)[i]; // e-mail
}

The problem is it only prints the one name and insert it in the first td. And the e-mail adresses can't be retrieved. I'm still a beginner in Regex so I can't see what I'm doing wrong.

Any help would be appreciated!

Nisarg Shah
  • 14,151
  • 6
  • 34
  • 55
user3740970
  • 389
  • 1
  • 3
  • 16
  • 2
    [Obligatory "don't use regex on HTML"](https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags). If you actually have the name and email in separate cells, why not just get their text content from each cell? – VLAZ Mar 01 '19 at 18:06
  • I need to retrieve the names and e-mail adresses from a string and then insert them into the table – user3740970 Mar 01 '19 at 18:08
  • if your format is *always* the same for `firstName lastName (username) ;` then you should be able to look for the parens and brackets to find username and email. – Scrimothy Mar 01 '19 at 18:13
  • @VLAZ: OP isn't parsing HTML using regex. Can you explain whats wrong in doing that? He's just constructing a simple HTML construct and its not that there are some nested tag complications here. I think you should not overuse discouragement the moment you hear HTML with regex. – Pushpesh Kumar Rajwanshi Mar 01 '19 at 18:28

4 Answers4

1

First use a global match(). That will return just the strings captured. Then loop through that array of matches and use exec() on each individual user to separate out the name and email capture groups.

const regex = /([^ ]+ [^ ]+) \(.*?\) <(.*?)>/g;

const outlook = "Anders Jensen (EAAAANJE) <eaaaanje@students.eaax.dk>; Bodil Pedersen (EAAABOPE) <eaaabope@students.eaax.dk>; Åse Andersen (EAAAIDAN) <eaaaasan@students.eaax.dk>; Mühl Svendsen (EAAAPESV) <eaaamusv@students.eaax.dk>";

const tbody = document.getElementById('users')
  .getElementsByTagName('tbody')[0];
const users = outlook.match(regex);

users.forEach((user, index) => {
  const userRegex = /([^ ]+ [^ ]+) \(.*?\) <(.*?)>/;
  const userInfo = userRegex.exec(user);
  const row = tbody.insertRow(index);
  
  if (userInfo) {
    const nameCell = row.insertCell(0);
    const emailCell = row.insertCell(1);
    nameCell.innerHTML = userInfo[1];
    emailCell.innerHTML = userInfo[2];
  }
  
});
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}

th, td {
padding: 10px;
}
<table id="users">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
  
  </tbody>
</table>
Scrimothy
  • 2,536
  • 14
  • 23
0

Well regexName.exec(outlook).length is 1, so your loop is only ever going to run once. You might need to remove the matched string from outlook if you want to do it this way. However, I would suggest that you first split the outlook string by the ; and then use the length of that array as your loop condition. Your regex is fine I believe

// this is some example of the names & email adresses - they are fake
const outlook = "Anders Jensen (EAAAANJE) <eaaaanje@students.eaax.dk>; Bodil Pedersen (EAAABOPE) <eaaabope@students.eaax.dk>; Åse Andersen (EAAAIDAN) <eaaaasan@students.eaax.dk>; Mühl Svendsen (EAAAPESV) <eaaamusv@students.eaax.dk>";

// we find all the emails & names of the students
let regexEmail = /\<.*?\>/g;
let regexName = /(\w+\s\w+\s)/gi;

// an array of all the td-tags
let tdTags = [];

let fragments = outlook.split(';');
// The emails and names are inserted in the table
for(let i = 0; i < fragments.length; i++) {
  console.log(fragments[i])
  let name = fragments[i].match(regexName)
  let email = fragments[i].match(regexEmail)

  tdTags.push({ name, email: email });// e-mail
}
Sean Kelly
  • 901
  • 7
  • 27
  • i have tried to run the loop 10 times where the run condition is: i < 10 but with the same result – user3740970 Mar 01 '19 at 18:20
  • Well the problem is you're getting the same result every time. Like I mentioned, you'd need to remove the matched string in every iteration OR split the string by the semi-colon and just match the element in the array. Either way should work – Sean Kelly Mar 01 '19 at 18:23
-1

Once you have a string I would be using something like: string.match(/\<(.*?)\>/g)[0]

Chris H
  • 501
  • 1
  • 4
  • 15
-1

I know your question talks about regex, but I'd just use good old split:

// this is some example of the names & email adresses - they are fake
const outlook = "Anders Jensen (EAAAANJE) <eaaaanje@students.eaax.dk>; Bodil Pedersen (EAAABOPE) <eaaabope@students.eaax.dk>; Åse Andersen (EAAAIDAN) <eaaaasan@students.eaax.dk>; Mühl Svendsen (EAAAPESV) <eaaamusv@students.eaax.dk>";

// Get an array of the addresses by splitting on ;
const addresses = outlook.split(';').map(s => s.trim());
for (let address of addresses) {
  // Split each address on space
  const parts = address.split(' ');
  // the first two should be first and last name
  const name = `${parts[0]} ${parts[1]}`;
  // the fourth element should be the email address
  // remove the angle brackets
  const email = parts[3].replace(/(<|>)/g, '');
  // Do your table thing with the results
  console.log(name, email);
}
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122