0

The code below gives a final undefined part...trying to figure where the undefined part is created. Any thoughts?

jQuery(document).ready(function() {
  console.log("ok");
  var object = {};
  var text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
  var lines = text.split('\n');
  for (var line = 0; line < lines.length; line++) {
    //console.log(lines[line]);

    if (lines[line].startsWith("#DIM")) {
      //console.log(lines[line]);
      var myRegexp = /[^\s"]+|"([^"]*)"/gi;
      var row = [];
      do {
        //Each call to exec returns the next regex match as an array
        var match = myRegexp.exec(lines[line]);
        if (match != null) {
          //console.log(match);
          row.push(match[1] ? match[1] : match[0]);
          object[row[1]] = {
            namn: row[2]
          };
        }
        //console.log(row);
      } while (match != null);
    }
  }
  console.log(object);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Here's a fiddle.

2
  • The problem is that on your first pass, row has only one element in it (row[0]), so row[1] and row[2] are both undefined. But what is the end goal of this code? Commented Nov 3, 2021 at 9:53
  • It's unclear why, given 2 matching lines, you expect 3 output values. Can you provide an expected result? Commented Nov 3, 2021 at 10:41

1 Answer 1

1

The problem is that on your first pass, row has only one element in it (row[0]), so row[1] and row[2] are both undefined.

I think the goal of this code is to build an object with properties derived from the #DIM 1 "test" and #DIM 6 "test"2 lines, giving the properties the names "1", "2", etc. with the values of the text in quotes. If so, you don't need row at all, see comments:

const text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
const object = {};
// Use multiline flag so `^` matches start-of-line and
// $ matches end-of-line
const rexParseLine = /^#DIM\s+(\S+)\s+"([^"]+)"\s*$/gm;
let match;
while ((match = rexParseLine.exec(text)) !== null) {
    object[match[1]] = match[2];
}
console.log(object);

Note that I didn't split the text into lines first, the regular expression can handle working within lines if we use the multiline (m) flag. Here'sa breakdown of the regex:

  • ^#DIM - line starts with #DIM
  • \s+ - followed by one or more whitespace chars
  • (\S+) - followed by one or more non-whitespace chars that we capture
  • \s+ - followed by one or more whitespace chars
  • "([^"]+)" - followed by "s with text in-between that we capture
  • \s*$ - followed by optional whitespace and end-of-line

The g flag lets use use it in a loop to work through the text, and the m flag, again, changes the meaning of ^ and $.

Side note: In modern environments, we can use named capture groups to make that clearer:

const text = `#DATA1 1000
#DATA2 1000
#DATA3 2000
#DIM 1 "test"
#DIM 6 "test2"`;
const object = {};
// Use multiline flag so `^` matches start-of-line and
// $ matches end-of-line
const rexParseLine = /^#DIM\s+(?<key>\S+)\s+"(?<value>[^"]+)"\s*$/gm;
let match;
while ((match = rexParseLine.exec(text)) !== null) {
    const {key, value} = match.groups;
    object[key] = value;
}
console.log(object);


But I have to admit it's not clear to me why you were allowing for the first capture group to be empty, so that may need tweaking.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.