0

I'm trying to get all Youtube video IDs from string like this:

https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg

Following to this answers I wrote code:

var re = /(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.)?youtube\.com\/watch(?:\.php)?\?.*v=)([a-zA-Z0-9\-_]+)/g,
    str = 'https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg',
    match;

while (match = re.exec(str)) {
   if (match.index === re.lastIndex) {
      re.lastIndex++;
   }

   console.log(match[1]);
}

But console.log shows only last ID 97aiSGxmizg. What am I doing wrong?

  • How many matches do you expect? Do you also need to match `DOQsYk8cbnE` in `https://www.youtube.com watch?v=DOQsYk8cbnE`? – Wiktor Stribiżew Mar 21 '18 at 13:17
  • @WiktorStribiżew three matches: OovKTBO4aQs, DOQsYk8cbnE and 97aiSGxmizg –  Mar 21 '18 at 13:19
  • where you get this strange `str`? maybe you can ask for array instead? – apple apple Mar 21 '18 at 13:20
  • Try https://regex101.com/r/GBSiXs/1/ – Wiktor Stribiżew Mar 21 '18 at 13:20
  • if you are only getting youtube URLs, then why don't you just check for "v=" (some value) " " – Daniel Gale Mar 21 '18 at 13:20
  • @WiktorStribiżew sorry, there's was a typo in `str`. Now it's ok, but code is still doesn't work as I want –  Mar 21 '18 at 13:21
  • @DanielGale in common case, youtube has many types of URLs, so I took this regex because it works for all URLs types –  Mar 21 '18 at 13:23
  • @mplungjan of course I can split string with spaces, but I suppose it is not optimal decision –  Mar 21 '18 at 13:26
  • @TroyHambleton your regexp is not correct. its matching spaces between them – Shrihari Balasubramani Mar 21 '18 at 13:26
  • @ShrihariBalasubramani but it works well here https://regex101.com/r/Peu4Oq/1 –  Mar 21 '18 at 13:27
  • @ShrihariBalasubramani how can I update this regexp to make it work? https://regex101.com/r/Peu4Oq/2 –  Mar 21 '18 at 13:30
  • var re = /(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.)?youtube\.com\/watch(?:\.php)?\?[^ ]*v=)([a-zA-Z0-9\-_]+)/g; Please check my answer for more – Shrihari Balasubramani Mar 21 '18 at 13:36
  • @TroyHambleton I don't think you are covering all the scenarios. YouTube URLs come in several flavors other than `v=` - While this question doesn't answer your question and is php related it does lists a few of the YouTube URL formats in the question itself: https://stackoverflow.com/questions/7693218/youtube-i-d-parsing-for-new-url-formats such as `http://youtu.be/97aiSGxmizg` or `http://www.youtube.com/v/97aiSGxmizg` – Nope Mar 21 '18 at 13:40
  • @TroyHambleton in combination with map, not an issue – mplungjan Mar 21 '18 at 13:56

4 Answers4

1

Assuming v=something, try this (regex from Extract parameter value from url using regular expressions)

var regex = /\?v=([a-z0-9\-]+)\&?/gi, matches = [], index=1;
urls = "https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg";
while (match = regex.exec(urls)) matches.push(match[index])
console.log(matches)
mplungjan
  • 169,008
  • 28
  • 173
  • 236
1

Based on the posted string's format, v=id, one can do something as simple as split the string at space and the again, combined with reduce(), at v=, to get the successfully split'ed id's.

I also used an anonymous function (function(){...})(); to only have to run the split once.

Stack snippet

var str = 'https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg';

var list = str.split(' ').reduce(function(r, e) {
  (function(i){
    if (i.length > 1) r.push(i[1]);
  })(e.split('v='));  
  return r;
}, []);

console.log(list);

As mentioned, if there are other formats, one can easily use a regex, e.g.

Stack snippet

var str = 'https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg http://www.youtube.com/v/-wtIMTCHWuI http://youtu.be/-DOQsYk8cbnE';

var list = str.split(' ').reduce(function(r, e) {
  (function(i){
    if (i.length > 1) r.push(i[1]);
  })(e.split(/v=|v\/-|be\/-/));
  return r;
}, []);

console.log(list);
Asons
  • 84,923
  • 12
  • 110
  • 165
0

The capture group will only match the last match in that string.

Split the strings into an array and log them there:

var re = /(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.)?youtube\.com\/watch(?:\.php)?\?.*v=)([a-zA-Z0-9\-_]+)/g,
  str = 'https://www.youtube.com/watch?v=OovKTBO4aQs https://www.youtube.com/watch?v=DOQsYk8cbnE https://www.youtube.com/watch?v=97aiSGxmizg',
  strs = str.split(' ');


strs.forEach((str) => {
  var match;
  while (match = re.exec(str)) {
    if (match.index === re.lastIndex) {
      re.lastIndex++;
    }
    console.log(match[1]);
  }
})
KyleFairns
  • 2,947
  • 1
  • 15
  • 35
-1

You regex is not correct.

The correct regex would be like this:

var re = /(?:https?:\/\/)?(?:youtu\.be\/|(?:www\.)?youtube\.com\/watch(?:\.php)?\?[^ ]*v=)([a-zA-Z0-9\-_]+)/g;

var str = 'https://www.youtube.com/watch?v=OovKTBO4aQs jiberish https://www.youtube.com/watch?v=DOQsYk8cbnE  jiberish a https://www.youtube.com/watch?v=97aiSGxmizg'
console.log(str.match(re))
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • As you can see in the [mcve] I made from your answer, the result is not a list of IDs since you do not show the captures – mplungjan Mar 21 '18 at 14:51