Один emoji соответствует регулярному выражению, но тот же самый не соответствует Javascript [duplicate]

Я проверил это в командной строке

# create dummy file. last line doesn't end with newline
printf "%i\n%i\nNo-newline-here" >testing

Протестируйте вашу первую форму (трубопровод к while-loop)

cat testing | while read line; do echo $line; done

Это пропустит последнюю строку, что имеет смысл поскольку read получает только вход, который заканчивается символом новой строки.


Тест со второй формой (подстановка команды)

for line in `cat testbed1` ; do echo $line; done

Это также возвращает последнюю строку

read получает вход только в том случае, если он завершен символом новой строки, поэтому вы пропустите последнюю строку.

С другой стороны, во второй форме

`cat testing` 

расширяется до формы

line1\nline2\n...lineM 

, которая разделяется оболочкой на несколько полей с использованием IFS, поэтому вы получаете

line1 line2 line3 ... lineM 

Вот почему вы все равно получаете последнюю строку .

p / s: Я не понимаю, как вы получаете первую форму работы ...

213
задан zb226 9 June 2017 в 08:55
поделиться

6 ответов

Объект RegExp отслеживает lastIndex , где произошло совпадение, поэтому в последующих совпадениях он будет начинаться с последнего используемого индекса, а не 0. Посмотрите:

var query = 'Foo B';
var re = new RegExp(query, 'gi');
var result = [];
result.push(re.test('Foo Bar'));

alert(re.lastIndex);

result.push(re.test('Foo Bar'));

Если вы не хотите вручную сбросить lastIndex до 0 после каждого теста, просто удалите флаг g.

Вот алгоритм, который специфицирует спецификация (раздел 15.10.6.2): ​​

RegExp.prototype.exec (string)

Выполняет сопоставление регулярных выражений строки с регулярным выражением и возвращает объект Array, содержащий результаты совпадение или null, если строка не соответствует. Строка ToString (string) выполняется для поиска регулярного выражения следующим образом:

  1. Пусть S - значение ToString (string) .
  2. Пусть length - длина S.
  3. Пусть lastIndex - значение свойства lastIndex.
  4. Пусть i - значение ToInteger (lastIndex) .
  5. Если глобальное свойство ложно, пусть i = 0.
  6. Если I & lt; 0 или I> length, тогда установите lastIndex равным 0 и верните null.
  7. Вызов [[Match]], давая ему аргументы S и i. Если [[Match]] возвратил ошибку, перейдите к шагу 8; в противном случае r будет его результатом состояния и перейдите к шагу 10.
  8. Пусть i = i + 1.
  9. Перейдите к шагу 6. ​​
  10. Пусть e будет r endIndex.
  11. Если глобальное свойство истинно, установите lastIndex в e.
  12. Пусть n - длина массива захватов r. (Это то же значение, что и для NCapturingParens от 15.10.2.1.)
  13. Возвращает новый массив со следующими свойствами: Свойство index устанавливается в позицию согласованной подстроки в полной строке S. input свойство установлено равным S. Свойство length установлено в n + 1. Свойство 0 задано подстрочной подстрокой (т. е. частью S между смещением i включительно и смещением e exclusive). Для каждого целого i такого, что I> 0 и I ≤ n, задайте свойство с именем ToString (i) i-му элементу массива захватов r.
272
ответ дан Joe White 15 August 2018 в 19:55
поделиться
  • 1
    Это похоже на руководство Hitchhiker по дизайну Galaxy API. «Эта ловушка, в которую вы попали, была полностью задокументирована в спецификации в течение нескольких лет, если вы только потрудились проверить & quot; – Retsam 22 August 2013 в 20:54
  • 2
    Липкий флаг Firefox не делает того, что вы подразумеваете. Скорее, он действует так, как если бы в начале регулярного выражения было ^, ИСКЛЮЧИТЕ, что это соответствует строке current (lastIndex), а не началу строки. Вы эффективно проверяете, соответствует ли регулярное выражение «прямо здесь». вместо "где-нибудь после lastIndex". См. Ссылку, которую вы указали! – Doin 14 January 2014 в 14:15
  • 3
    Вступительное заявление этого ответа просто неверно. Вы выделили шаг 3 спецификации, который ничего не говорит. Фактическое влияние lastIndex находится на шагах 5, 6 и 11. Ваше вступительное утверждение верно только в том случае, если GLOBAL FLAG SET. – Prestaul 28 August 2014 в 19:38
  • 4
    @Престаул, да, ты прав, что он не упоминает глобальный флаг. Вероятно, (не помню, что я тогда думал) неявно из-за того, как вставлен вопрос. Не стесняйтесь редактировать ответ или удалять его и ссылаться на свой ответ. Кроме того, позвольте мне успокоить вас, что вы лучше меня. Наслаждайтесь! – Ionuț G. Stan 29 August 2014 в 01:45
  • 5
    @ IonuţG.Stan, извините, если мой предыдущий комментарий казался атакующим, это было не мое намерение. На данный момент я не могу его отредактировать, но я не пытался кричать, просто чтобы привлечь внимание к основному моменту моего комментария. Виноват! – Prestaul 29 August 2014 в 23:11

У меня была функция:

function parseDevName(name) {
  var re = /^([^-]+)-([^-]+)-([^-]+)$/g;
  var match = re.exec(name);
  return match.slice(1,4);
}

var rv = parseDevName("BR-H-01");
rv = parseDevName("BR-H-01");

Первый вызов работает. Второй звонок - нет. Операция slice жалуется на нулевое значение. Я предполагаю, что это из-за re.lastIndex. Это странно, потому что я ожидал бы, что новый RegExp будет выделяться каждый раз, когда функция вызывается и не разделяется между несколькими вызовами моей функции.

Когда я изменил ее на:

var re = new RegExp('^([^-]+)-([^-]+)-([^-]+)$', 'g');

Тогда я не получаю эффект удержания lastIndex. Он работает так, как я ожидал.

0
ответ дан Chelmite 15 August 2018 в 19:55
поделиться

RegExp.prototype.test обновляет свойство регулярных выражений lastIndex, чтобы каждый тест начинался с остановки последнего. Я бы предложил использовать String.prototype.match, поскольку он не обновляет свойство lastIndex:

!!'Foo Bar'.match(re); // -> true
!!'Foo Bar'.match(re); // -> true

Примечание: !! преобразует его в логическое, а затем инвертирует логическое значение, чтобы он отражал результат .

В качестве альтернативы вы можете просто сбросить свойство lastIndex:

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
33
ответ дан James 15 August 2018 в 19:55
поделиться

Удаление глобального флага f3 устранит вашу проблему.

var re = new RegExp(query, 'gi');

Должно быть

var re = new RegExp(query, 'i');
9
ответ дан Jonatas Walker 15 August 2018 в 19:55
поделиться

Вы используете один объект RegExp и выполняете его несколько раз. При каждом последующем выполнении он продолжается от последнего индекса соответствия.

Вам нужно «перезагрузить» регулярное выражение для начала с начала перед каждым исполнением:

result.push(re.test('Foo Bar'));
re.lastIndex = 0;
result.push(re.test('Foo Bar'));
// result is now [true, true]

Сказав это может быть более читаемым каждый раз создавать новый объект RegExp (служебные данные минимальны, поскольку RegExp кэшируется в любом случае):

result.push((/Foo B/gi).test(stringA));
result.push((/Foo B/gi).test(stringB));
61
ответ дан Roatin Marth 15 August 2018 в 19:55
поделиться

Использование флага / g сообщает ему продолжить поиск после хита.

Если совпадение завершается успешно, метод exec () возвращает массив и обновляет свойства объекта регулярного выражения.

Перед первым поиском:

myRegex.lastIndex
//is 0

После первого поиска

myRegex.lastIndex
//is 8

Удалите g и он выйдет из поиска после каждого вызова к exec ().

0
ответ дан Scott Schlechtleitner 15 August 2018 в 19:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: