Я проверил это в командной строке
# 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: Я не понимаю, как вы получаете первую форму работы ...
Объект 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) выполняется для поиска регулярного выражения следующим образом:
blockquote>
- Пусть S - значение ToString (string) .
- Пусть length - длина S.
- Пусть lastIndex - значение свойства lastIndex.
- Пусть i - значение ToInteger (lastIndex) .
- Если глобальное свойство ложно, пусть i = 0.
- Если I & lt; 0 или I> length, тогда установите lastIndex равным 0 и верните null.
- Вызов [[Match]], давая ему аргументы S и i. Если [[Match]] возвратил ошибку, перейдите к шагу 8; в противном случае r будет его результатом состояния и перейдите к шагу 10.
- Пусть i = i + 1.
- Перейдите к шагу 6.
- Пусть e будет r endIndex.
- Если глобальное свойство истинно, установите lastIndex в e.
- Пусть n - длина массива захватов r. (Это то же значение, что и для NCapturingParens от 15.10.2.1.)
- Возвращает новый массив со следующими свойствами: Свойство index устанавливается в позицию согласованной подстроки в полной строке S. input свойство установлено равным S. Свойство length установлено в n + 1. Свойство 0 задано подстрочной подстрокой (т. е. частью S между смещением i включительно и смещением e exclusive). Для каждого целого i такого, что I> 0 и I ≤ n, задайте свойство с именем ToString (i) i-му элементу массива захватов r.
У меня была функция:
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
. Он работает так, как я ожидал.
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'));
Удаление глобального флага f3 устранит вашу проблему.
var re = new RegExp(query, 'gi');
Должно быть
var re = new RegExp(query, 'i');
Вы используете один объект 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));
Использование флага / g сообщает ему продолжить поиск после хита.
Перед первым поиском:
myRegex.lastIndex
//is 0
После первого поиска
myRegex.lastIndex
//is 8
Удалите g и он выйдет из поиска после каждого вызова к exec ().
lastIndex
находится на шагах 5, 6 и 11. Ваше вступительное утверждение верно только в том случае, если GLOBAL FLAG SET. – Prestaul 28 August 2014 в 19:38