Оказывается, это немного сложнее, чем кажется, и ответ будет зависеть от того, что вы хотите сделать с заполнителями, и какой язык / спецификацию вы используете как для printf, так и для регулярных выражений.
Чтобы дать вам пример того, как это выглядит на практике, вот регулярное выражение-заполнитель из библиотеки sprintf.js, которое соответствует ее собственной спецификации заполнителя , которая похожа, но не идентична c ++ spec , который похож, но не идентичен php spec :
placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fiosuxX])/,
Вы можете получить отличное объяснение всех битов и кусочков, используя что-то вроде regex101 https://regex101.com/r/bV9nT8/1 но есть две ключевые вещи, которые следует учитывать в широком смысле:
1) '^' в начале: в реализации Regexp на языке javascript отсутствует \ G "Конец предыдущего соответствия"якорь, который делает невозможным сопоставление смежных заполнителей ('%s%s'
=> ['%s','%s']
), игнорируя экранированные знаки '%' ('%s%%s'
=> ['%s'])
. В результате эта прога библиотекиrammatics обрабатывает простой текст и %%
подстроки перед попыткой регулярного выражения заполнителя.
2) Группы захвата: как часть библиотеки синтаксического анализа, это регулярное выражение захватывает много вещей, которые ему нужно знать:
- цифры в
$1s
(индекс аргумента) - имя в
$(variableName)s
+
после скобок, если оно присутствует - Либо 0, либо
'
, за которым следует другая последовательность символов (я думаю, что это символ заполнения) - необязательный
-
символ - Дополнительные цифры (минимальная ширина поля)
- Больше цифр (точность с плавающей запятой)
- спецификатор типа
В зависимости от вашей цели вы, вероятно, захотите подмножество этих вещей, или, возможно, ни одну из них, столько одна группа захвата для всего выражения, например:
var regexForPlaceholders = /(?:\x25\x25)|(\x25(?:(?:[1-9]\d*)\$|\((?:[^\)]+)\))?(?:\+)?(?:0|'[^$])?(?:-)?(?:\d+)?(?:\.(?:\d+))?(?:[b-fiosuxX]))/g;
function placeholders(string ){
return ( string.match( regexForPlaceholders ) || [] )
.filter( function( v ) {
return v !== '\x25\x25';
} );
}