Регулярное выражение для сопоставления буквенно-цифровых символов в строке, содержащей URL-адреса

Учитывая несколько сценариев, как я могу сопоставить и извлечь буквенно-цифровые символы (и символы) в строке, содержащей URL-адреса? В настоящее время я использую Google Apps Script для извлечения простого основного текста текста с гиперссылкой из сообщения потока Gmail, и в основном я хотел бы сопоставить и извлечь заголовок из некоторых строк следующим образом:

var scenario1 = "Testing: Stack Overflow Title 123? https://www.stackoverflow.com";

... в котором я хотел бы выводить только: "Testing: Stack Overflow Title 123?"

Вот еще один сценарий:

var scenario2 = "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com";

... снова, в котором я хотел бы выводить только: "Testing: Stack Overflow Title 123?"

Я попробовал следующее для первоначального тестирования, чтобы увидеть, содержит ли String сначала URL-адрес (в котором я подтвердил, что регулярное выражение для сопоставления URL-адресов работает и выводит: https://www.stackoverflow.com), а затем проверяет, существует ли заголовок, чтобы в конечном итоге извлечь его, но безрезультатно:

var scenario1 = "Testing: Stack Overflow Title 123? https://www.stackoverflow.com";
var scenario2 = "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com";
var urlRegex = /(http|https|ftp|ftps)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?/;
var titleRegex = /^[a-zA-Z0-9_:?']*$/;
var containsUrl = urlRegex.test(element);
if (containsUrl) {
    var containsTitle = titleRegex.test(scenario1);
    if (containsTitle) { // No match, and doesn't run
      var title = titleRegex.exec(element)[0];
      Logger.log("title: " + title);
    }
}

По сути, мне нужен шаблон Regex, который соответствует ВСЕМ, кроме URL-адресов, если это возможно.

Может ли быть несколько подстрок, отличных от URL? (в каком случае вам нужен массив этих подстрок?)

CertainPerformance 02.02.2019 18:37

Будут ли все URL-адреса начинаться с протокола?

guest271314 02.02.2019 19:02
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
208
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Одной из возможностей может быть сопоставление до тех пор, пока вы не встретите первый URL-адрес, используя либо группу, либо положительный просмотр вперед.

Использование положительного прогноза, который может выглядеть так:

\bTesting: .*?(?=\s*(?:https?|ftps?)://)

const regexLookahead = /\bTesting: .*?(?=\s*(?:https?|ftps?)://)/;
[
  "Testing: Stack Overflow Title 123? https://www.stackoverflow.com",
  "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com"
].forEach(s => console.info(s.match(regexLookahead)[0]));

Используя группу захвата, где ваше значение будет в первой группе захвата:

(\bTesting: .*?)\s*(?:https?|ftps?)://

const regexGroup = /(\bTesting: .*?)\s*(?:https?|ftps?):///;
[
  "Testing: Stack Overflow Title 123? https://www.stackoverflow.com",
  "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com"
].forEach(s => console.info(s.match(regexGroup)[1]));

Если вы хотите сохранить все, кроме URL-адресов, вы можете сопоставить их и заменить пустой строкой:

\s*(?:https?|ftps?)://\S+

[
  "Testing: Stack Overflow Title 123? https://www.stackoverflow.com",
  "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com",
  "https://www.stackoverflow.com test https://www.stackoverflow.com test https://www.stackoverflow.com test",
  "https://www.stackoverflow.com test",
  "test https://www.stackoverflow.com"
].forEach(s => console.info(s.replace(/\s*(?:https?|ftps?)://\S+/g, '').trim()));

Однако это зависит от подстрок, отличных от URL, начинающихся с границы слова, и, к сожалению, просмотр назад (для пробела или для ^) пока недостаточно широко поддерживается, как вы, вероятно, знаете, не уверен, как я это исправлю

CertainPerformance 02.02.2019 18:52

@CertainPerformance Я вижу, вы имеете в виду, что я также добавил заменяющий вариант.

The fourth bird 02.02.2019 19:09

Вы можете использовать символы пробела .split() и результирующий массив .filter(), чтобы исключить элементы, которые начинаются с указанных протоколов или заканчиваются словом, затем символом точки, затем словом и концом строки.

const splitURL = s => s.split` `.filter(w => !/^\w+(?=://)|\w+\.\w+$/.test(w)).join` `;
 
var scenario1 = "Testing: Stack Overflow Title 123? https://www.stackoverflow.com";

var scenario2 = "https://www.stackoverflow.com Testing: Stack Overflow Title 123? https://www.stackoverflow.com";

console.info(splitURL(scenario1), splitURL(scenario2));

Другой вариант - .replace() URL с пустой строкой, используя urlRegexps.replace(/(http|https|ftp|ftps)\://[a-zA-Z0-9\-\.]+\.[a-z‌​A-Z]{2,3}(/\S*)?/g, '')

guest271314 02.02.2019 19:31
Ответ принят как подходящий

Мы можем захватить любой последовательный текст, за исключением того, что выглядит как URL-адрес, используя это регулярное выражение,

(?:^|\s+)((?:(?!://).)*)(?=\s|$)

Объяснение:

  • (?:^|\s) — соответствует либо началу строки, либо одному или нескольким пробелам.
  • ((?:(?!://).)*) — Соответствует любому тексту, кроме того, который содержит ://, буквально идентифицируя его как URL-адрес.
  • (?=\s|$) - Положительный просмотр вперед, чтобы убедиться, что за ним следует пробел или конец строки

Демо

Это соответствует и фиксирует любой последовательный текст, кроме URL-адресов. Надеюсь, что это работает для вас.

Вот демонстрация Javascript.

var arr = ['Testing1: Stack Overflow Title 123? https://www.stackoverflow.com','https://www.stackoverflow.com    Testing2: Stack Overflow Title xyz? https://www.stackoverflow.com Hello this is simple text ftp://www.downloads.com/']

for (s of arr) {
	var reg = /(?:^|\s+)((?:(?!://).)*)(?=\s|$)/g;
	match = reg.exec(s);
	while (match != null) {
		console.info(match[1])
		match = reg.exec(s);
	}
}

Кроме того, как я вижу, вы хотите ограничить количество символов в соответствующем заголовке, вы можете использовать свой набор символов [a-zA-Z0-9_:?' ] (добавлен пробел в вашем наборе символов, чтобы также можно было записывать пробелы) вместо . в моем регулярном выражении и использовать следующее регулярное выражение, чтобы быть более точным, чтобы избежать захвата заголовка с непредусмотренными символами,

(?:^|\s+)((?:(?!://)[a-zA-Z0-9_:?' ])*)(?=\s|$)

Демонстрация с вашим набором символов заголовка

Это также соответствует ведущим пробелам, что, вероятно, нежелательно.

CertainPerformance 02.02.2019 19:09

Group1 захватывает текст, который не содержит пробелов.

Pushpesh Kumar Rajwanshi 02.02.2019 19:09

Я мог бы использовать положительный просмотр для целых совпадений, чтобы не содержать лишних пробелов, но многие старые инструменты/браузеры не поддерживают EcmaScript2018, и, следовательно, все они не будут работать, поэтому пришлось использовать групповой захват. И группа не содержит дополнительных начальных/конечных пробелов, как видно из моей демонстрации, которая должна работать для OP.

Pushpesh Kumar Rajwanshi 02.02.2019 19:28

@PushpeshKumarRajwanshi +1 отлично

Mohammed Elhag 02.02.2019 20:25

Другие вопросы по теме