Javascript: несколько регулярных выражений с одним шаблоном [дубликат]

Компиляция программы на C ++ выполняется в несколько этапов, как указано в 2.2 (кредиты для Кейта Томпсона для ссылки) :

Превалирование среди правил синтаксиса

  1. Физические символы исходного файла сопоставляются в соответствии с реализацией в соответствии с базовым набором символов источника (ввод символов новой строки для индикаторов конца строки) при необходимости. [SNIP]
  2. Каждый экземпляр символа обратной косой черты (\), за которым сразу следует символ новой строки, удаляется, сплайсируя физические исходные строки для формирования логических строк источника. [SNIP]
  3. Исходный файл разбивается на токены предварительной обработки (2.5) и последовательности символов пробела (включая комментарии). [SNIP]
  4. Выполнены предпроцессорные директивы, макро-вызовы разворачиваются и выполняются операторные выражения _Pragma. [SNIP]
  5. Каждый элемент набора символов в символьном литерале или строковый литерал, а также каждая escape-последовательность и универсальное имя-символа в символьном литерале или не- -raw строковый литерал, преобразуется в соответствующий член набора символов выполнения; [SNIP]
  6. Соединительные маркеры литералов строки объединены.
  7. Символы пробела, разделяющие токены, уже не являются значимыми. Каждый токен предварительной обработки преобразуется в токен. (2.7). Результирующие маркеры синтаксически и семантически анализируются и переводятся как единица перевода. [SNIP]
  8. Устанавливаемые единицы перевода и единицы экземпляра объединяются следующим образом: [SNIP]
  9. Все ссылки на внешние сущности решена. Компоненты библиотеки связаны для удовлетворения внешних ссылок на объекты, не определенные в текущем переводе. Весь такой переводчик выводится в образ программы, который содержит информацию, необходимую для выполнения в среде выполнения. (акцент мой)

[footnote] Реализации должны вести себя так, как если бы эти отдельные фазы происходили, хотя на практике различные фазы могли быть свернуты вместе.

Указанные ошибки возникают на этом последнем этапе компиляции, чаще всего называемом связыванием. Это в основном означает, что вы собрали кучу файлов реализации в объектные файлы или библиотеки, и теперь вы хотите заставить их работать вместе.

Скажите, что вы определили символ a в a.cpp. Теперь b.cpp объявил этот символ и использовал его. Перед связыванием он просто предполагает, что этот символ был определен где-то , но он пока не заботится о том, где. Фаза связывания отвечает за поиск символа и правильную привязку его к b.cpp (ну, собственно, к объекту или библиотеке, которая его использует).

Если вы используете Microsoft Visual Studio, вы будете см., что проекты генерируют файлы .lib. Они содержат таблицу экспортированных символов и таблицу импортированных символов. Импортированные символы разрешены против библиотек, на которые вы ссылаетесь, и экспортированные символы предоставляются для библиотек, которые используют этот .lib (если есть).

Подобные механизмы существуют для других компиляторов / платформ.

Общие сообщения об ошибках: error LNK2001, error LNK1120, error LNK2019 для Microsoft Visual Studio и undefined reference to symbolName для GCC.

Код:

struct X
{
   virtual void foo();
};
struct Y : X
{
   void foo() {}
};
struct A
{
   virtual ~A() = 0;
};
struct B: A
{
   virtual ~B(){}
};
extern int x;
void foo();
int main()
{
   x = 0;
   foo();
   Y y;
   B b;
}

генерирует следующие ошибки с GCC:

/home/AbiSfw/ccvvuHoX.o: In function `main':
prog.cpp:(.text+0x10): undefined reference to `x'
prog.cpp:(.text+0x19): undefined reference to `foo()'
prog.cpp:(.text+0x2d): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD1Ev[B::~B()]+0xb): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o: In function `B::~B()':
prog.cpp:(.text._ZN1BD0Ev[B::~B()]+0x12): undefined reference to `A::~A()'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1Y[typeinfo for Y]+0x8): undefined reference to `typeinfo for X'
/home/AbiSfw/ccvvuHoX.o:(.rodata._ZTI1B[typeinfo for B]+0x8): undefined reference to `typeinfo for A'
collect2: ld returned 1 exit status

и аналогичные ошибки с Microsoft Visual Studio:

1>test2.obj : error LNK2001: unresolved external symbol "void __cdecl foo(void)" (?foo@@YAXXZ)
1>test2.obj : error LNK2001: unresolved external symbol "int x" (?x@@3HA)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual __thiscall A::~A(void)" (??1A@@UAE@XZ)
1>test2.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall X::foo(void)" (?foo@X@@UAEXXZ)
1>...\test2.exe : fatal error LNK1120: 4 unresolved externals

. Общие причины включают в себя:

15
задан David Starkey 21 August 2013 в 17:14
поделиться

6 ответов

Литеральное выражение RegExp.$1 даст вам значение первой группы захвата последнего регулярного выражения. Независимо от этого регулярного выражения.

Например:

var match = /_(.*)_/.exec('_test_');

var newMatch = '123-abc'.match(/(\d*)-(\w*)/);
var num = RegExp.$1; // '123';

RegExp.$1 доступен в глобальном масштабе, поэтому к нему можно получить доступ из любой точки вашей страницы, независимо от того, где само регулярное выражение было ran.

Я никогда не видел этот синтаксис, используемый перед тем, как увидеть этот вопрос, и я бы не предложил его использовать, поскольку я не могу найти документацию на нем. Кроме того, любое регулярное выражение запускается на вашей странице, вне зависимости от того, где будет изменено это свойство. Если вы хотите получить группы захвата, я бы использовал массивы, возвращенные из String.match или RegExp.exec.

EDIT: Я нашел некоторую документацию об этом: http: // msdn .microsoft.com / en-us / library / ie / 24th3sah (v = vs.94) .aspx

EDIT 2: Я нашел дополнительную информацию об этом: https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#RegExp_Properties

RegExp.$1 устарел. Это означает, что будущие браузеры могут удалить эту «функцию», поэтому я предлагаю не использовать ее.

17
ответ дан Rocket Hazmat 26 August 2018 в 12:33
поделиться

$1 вернет первую группу, которая соответствует регулярному выражению.

В вашем примере значение, хранящееся в $1, соответствует любому .+

. группа обозначается скобками, и вы можете иметь кратность. Каждая сохраненная группа будет просто увеличивать цифру с помощью $, то есть $1, $2, $3...

Пример:

Если ваш вход был __product[Version 12 Coupe], тогда $1 будет содержать Version 12 Coupe

3
ответ дан David Starkey 26 August 2018 в 12:33
поделиться

Чтобы добавить некоторые детали:

(Как уже было сказано), RegExp.$n -property (где n - это одна цифра 1-9) возвращает последний n-й скобок (захваченный ) подстроку в матче.

Эти свойства были впервые реализованы в JavaScript 1.2 и устарели в JavaScript 1.5 - когда RegExp подверглись серьезному изменению, и многие из результатов RegExp.prototype.exec(string) были перемещены из объекта RegExp в RegExp ] и все свойства .$ (и их версии с полным именем (кроме .multiline)) «ушли».


Нестандартные1 $1, $2, $3, $4, $5, $6, $7, $8, $9 являются статическими и доступными только для чтения свойствами регулярных выражений (которые содержат совпадающие подстроки в скобках) и изменяются всякий раз, когда они успешны сделаны совпадения.

Они не являются свойством отдельного объекта регулярного выражения. Вместо этого вы всегда используете их как RegExp.$1, ..., RegExp.$9.

Количество возможных подстрок в скобках неограниченно (конечно), но объект RegExp может удерживать только последний 9.

1 Нестандартно = не является частью любой текущей спецификации!


Вы можете найти определение и ссылки в следующих разделах ECMA-262 3 Особенности:

  • 15.5.4.10 - String.prototype.match(regexp)
  • 15.5.4.11 - String.prototype.replace(regexp)
  • 15.10.2.1 - Обозначение объекта RegExp NCapturingParens
  • 15.10.6.2 - RegExp.prototype.exec(string)
0
ответ дан eyecatchUp 26 August 2018 в 12:33
поделиться

$1 - это то, что согласовано в первом захвате. Если у вас больше захватов, вы можете использовать $2, $3 и т. Д.

Пример:

"abc".replace(/(.)/, "$1$1"); // aabc
"abc".replace(/(.{2})/, "$1$1"); // ababc
"abc".replace(/(.)(.)/, "$2$1"); // bac
0
ответ дан Halcyon 26 August 2018 в 12:33
поделиться

Они работают вместе с захватывающими круглыми скобками. Например, /(foo)/ соответствует и запоминает «foo» в «foo bar». Соответствующая подстрока может быть вызвана из результирующих элементов массива [1], ..., [n] или из предопределенных свойств объекта RegExp $ 1, ..., $ 9.

В вашем примере $1 относится к совпадению, сделанному (.+)

См. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

3
ответ дан j08691 26 August 2018 в 12:33
поделиться

Как было сказано ранее, эти конструкции называются захватывающими круглыми скобками, и они в основном используются для ссылки на совпадения, сохраненные / сохраненные после успешного выполнения связанной с RegExp операции.

Кроме того, как было сказано ранее, я не рекомендую использовать ни один из них в вашем коде, если не будет обеспечена хорошо контролируемая среда / контекст, например, тот, который предоставляется встроенным методом replace(), найденным в String.prototype.

0
ответ дан Mr. X 26 August 2018 в 12:33
поделиться
Другие вопросы по тегам:

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