Строки и форматирование
Эти теги придают форму строке как шаг вычисления. Они живут внутри
<compute>, рядом с <gen> в
<sequence> и читают другие последовательности
через <field name="…"/> — те же имена, что и в
${{…}}.
Большинство из них (mask, case, slice, replace, trim, group) доступны
ещё двумя способами — как атрибут <gen>
(mask= / case=) и как фильтр в интерполяции (${{X | mask:…}}). Руководство
Маски и регистр показывает эти способы с готовым
выводом. Берите тег compute, когда форматирование — звено вычисления:
например, наложить маску на число и затем поднять регистр, прежде чем допишется
контрольная цифра. <concat>, <str> и <pad> существуют только как теги
compute.
Примеры вывода на этой странице иллюстративны — точные значения могут отличаться
от версии к версии ядра. Важна форма каждого преобразования. В примерах стоит
order="sequential", поэтому входные значения стабильны и повторяются по порядку.
Сборка и регистр
<concat> — склеить части в строку
Принимает любое число значений → отдаёт строку. Число по дороге становится своими цифрами.
<concat> приводит каждого ребёнка к строке и склеивает их по порядку, без
разделителя. В отличие от <add>, это строковая операция:
<concat> из "12" и "3" даёт "123", а не 15. Целое пишется своими
десятичными цифрами; ребёнка-список сначала нужно превратить в строку через
<join>.
Когда применять: когда вы собираете идентификатор из кусков — префикс, поле и вычисленная контрольная цифра.
<sequence name="Num"><gen type="number" value="100..999"/></sequence>
<sequence name="Year"><gen type="number" value="20..24"/></sequence>
<sequence name="Code">
<compute><result>
<concat><str v="ЗАК-"/><field name="Year"/><str v="-"/><field name="Num"/></concat>
</result></compute>
</sequence>
...
<data>${{Code}}</data>
ЗАК-24-692 ЗАК-21-695 ЗАК-23-979 ЗАК-24-326 ЗАК-24-587
Встроенного разделителя нет — дефисы это отдельные дети <str v="-"/>. Дописать
вычисленную контрольную цифру — тот же приём: назовите остаток через
<let>, затем приклейте его (целое само станет текстом).
<sequence name="Base"><gen type="number" value="1000..9999"/></sequence>
<sequence name="Full">
<compute>
<let name="c"><mod><to_number><field name="Base"/></to_number><int v="7"/></mod></let>
<result><concat><field name="Base"/><str v="-"/><var name="c"/></concat></result>
</compute>
</sequence>
...
<data>${{Full}}</data>
5962-5 4783-2 6257-6 2280-5 6591-4
<str> — строковый литерал
Принимает ничего; текст живёт в v= → отдаёт строку.
<str v="…"/> — это строковый литерал; текст пишется в атрибуте v (в TDC теги
не могут держать текст между <тег> и </тег>).
Когда применять: когда нужен фиксированный префикс, разделитель внутри
<concat> или символы дополнения — например, <str v=" "/>, который подставляет
лишние пробелы в примере с <trim> ниже.
<upper> / <lower> / <capitalize> / <title> — регистр
Принимает одну строку → отдаёт строку той же длины.
Четыре преобразования регистра, каждое берёт одного ребёнка-строку:
| Тег | Что делает |
|---|---|
<upper> | ВЕСЬ ВЕРХНИЙ регистр |
<lower> | весь нижний регистр |
<capitalize> | только первая буква заглавная, остальное как есть |
<title> | первая буква каждого слова заглавная, остальное как есть |
Когда применять: когда данные приходят в «пёстром» регистре (разные источники, импорт) и нужен единый вид. Одна и та же строка через все четыре:
<sequence name="W"><gen type="text" value="iPhone ЧЕХОЛ,мария ИВАНОВА,АННА фон лее" order="sequential"/></sequence>
<sequence name="U"><compute><result><upper><field name="W"/></upper></result></compute></sequence>
<sequence name="L"><compute><result><lower><field name="W"/></lower></result></compute></sequence>
<sequence name="C"><compute><result><capitalize><field name="W"/></capitalize></result></compute></sequence>
<sequence name="T"><compute><result><title><field name="W"/></title></result></compute></sequence>
...
<data>${{W}} -> upper=${{U}} | lower=${{L}} | capitalize=${{C}} | title=${{T}}</data>
iPhone ЧЕХОЛ -> upper=IPHONE ЧЕХОЛ | lower=iphone чехол | capitalize=IPhone ЧЕХОЛ | title=IPhone ЧЕХОЛ мария ИВАНОВА -> upper=МАРИЯ ИВАНОВА | lower=мария иванова | capitalize=Мария ИВАНОВА | title=Мария ИВАНОВА АННА фон лее -> upper=АННА ФОН ЛЕЕ | lower=анна фон лее | capitalize=АННА фон лее | title=АННА Фон Лее
capitalize трогает только самый первый символ (АННА фон лее осталась почти как
есть — её первая А уже заглавная), а title поднимает первую букву каждого
слова (фон → Фон, лее → Лее). upper / lower меняют всё.
Перестройка
Эти пять тегов переставляют символы строки. Все они также доступны как фильтры
${{X | …}} (см. Маски и регистр); показанная
здесь форма тега compute нужна, когда перестройка — звено вычисления.
<mask> — разбить и переставить по шаблону
Принимает одну строку плюс pattern= → отдаёт строку. Ничего не выдумывается: каждый символ результата либо пришёл со входа, либо записан литералом в шаблоне.
<mask pattern="…"> пересобирает строку по позиционному шаблону: он идёт слева
направо, каждый слот «съедает» кусок входа, а всё остальное печатается как
литерал.
| Слот | Что берёт из входа |
|---|---|
x | один символ |
w | одно слово (буквы до пробела) и проглатывает один пробел |
* | весь оставшийся вход |
\ | экранирует следующий символ (\x → буквальный x) |
| прочее | литерал: дефис, точка, пробел, скобки — печатается как есть |
pattern — единственный (обязательный) атрибут. Маска снисходительна и никогда
не падает: если x / w выходят за конец входа, они печатают пустоту, а любой
оставшийся хвост отбрасывается, если его не подберёт *.
Когда применять: когда значение приходит слитной строкой и нужны группы и разделители — СНИЛС, номер карты, телефон. Одни и те же цифры под одним шаблоном:
<sequence name="Raw"><gen type="text" value="37898432363,88973572402,85213975315,26324315851" order="sequential"/></sequence>
<sequence name="Masked">
<compute><result><mask pattern="xxx-xxx-xxx xx"><field name="Raw"/></mask></result></compute>
</sequence>
...
<data>${{Raw}} -> ${{Masked}}</data>
37898432363 -> 378-984-323 63 88973572402 -> 889-735-724 02 85213975315 -> 852-139-753 15 26324315851 -> 263-243-158 51
Каждый x берёт один символ; - и пробел — литералы, шаблон читается как
xxx-xxx-xxx xx.
Слот w — работать по словам. w берёт одно слово и проглатывает единственный
пробел за ним, поэтому лишнего отступа не остаётся:
<sequence name="Full"><gen type="text" value="ivan sergeevich petrov,petr ivanovich smirnov,anna sergeevna orlova" order="sequential"/></sequence>
<sequence name="First">
<compute><result><mask pattern="w: *"><field name="Full"/></mask></result></compute>
</sequence>
...
<data>${{Full}} -> ${{First}}</data>
ivan sergeevich petrov -> ivan: sergeevich petrov petr ivanovich smirnov -> petr: ivanovich smirnov anna sergeevna orlova -> anna: sergeevna orlova
Первый w берёт ivan и съедает его хвостовой пробел, печатается литерал : , а
* подбирает остаток. Пробела перед : нет — его проглотил w.
Экранирование — буквальный w. Чтобы напечатать символ-слот как есть,
экранируйте его через \:
<sequence name="Num"><gen type="text" value="1234,5678,9012" order="sequential"/></sequence>
<sequence name="Tagged">
<compute><result><mask pattern="\w-xxxx"><field name="Num"/></mask></result></compute>
</sequence>
...
<data>${{Num}} -> ${{Tagged}}</data>
1234 -> w-1234 5678 -> w-5678 9012 -> w-9012
\w — это буквальная буква w (не слот), затем литерал -, затем четыре x
берут четыре символа.
<slice> — подстрока по индексам
Принимает одну строку плюс from= и необязательный to= → отдаёт строку. Счёт с 0, отрицательный from считает от конца, а диапазон за пределом даёт пустую строку, а не ошибку.
<slice from="…" to="…"> вырезает подстроку на полуоткрытом диапазоне
[from, to): символ на позиции from входит, символ на позиции to — нет,
поэтому длина равна to − from. Индексы с нуля и считаются в кодовых
точках (Unicode режется по буквам, а не по байтам).
| Атрибут | Обязателен | Задаёт |
|---|---|---|
from | да | индекс первого символа (с нуля), включается |
to | нет | индекс сразу за последним символом; опущен → до конца |
Когда применять: когда нужна фиксированная часть значения — год или месяц даты, префикс кода, последние символы идентификатора.
<sequence name="D"><gen type="text" value="2020-05-14,2022-11-03,2020-01-30,2021-07-19" order="sequential"/></sequence>
<sequence name="Year"><compute><result><slice from="0" to="4"><field name="D"/></slice></result></compute></sequence>
<sequence name="Month"><compute><result><slice from="5" to="7"><field name="D"/></slice></result></compute></sequence>
<sequence name="Tail"><compute><result><slice from="5"><field name="D"/></slice></result></compute></sequence>
...
<data>${{D}} -> year=${{Year}} | month=${{Month}} | tail=${{Tail}}</data>
2020-05-14 -> year=2020 | month=05 | tail=05-14 2022-11-03 -> year=2022 | month=11 | tail=11-03 2020-01-30 -> year=2020 | month=01 | tail=01-30 2021-07-19 -> year=2021 | month=07 | tail=07-19
from=0 to=4 берёт символы 0–3 (год); from=5 to=7 берёт 5–6 (месяц — дефис на
индексе 4 не входит); from=5 без to идёт от индекса 5 до конца.
<replace> — заменить все вхождения
Принимает одну строку плюс from= и to= → отдаёт строку. from= сопоставляется буквально, а не как регулярное выражение, и заменяются все вхождения.
<replace from="…" to="…"> заменяет все вхождения буквальной подстроки from
на to. Оба — обычные строки, а не регулярные выражения: что написали, то и
ищется дословно. Если from пуста или не найдена, строка возвращается без
изменений.
| Атрибут | Обязателен | Задаёт |
|---|---|---|
from | да | что искать (литерал) |
to | да | на что заменить |
Когда применять: когда нужно поменять разделитель (дефис → слэш в дате) или
убрать символ целиком (to="" удаляет каждое совпадение):
<sequence name="D"><gen type="text" value="2020-05-14,2022-11-03,2020-01-30,2021-07-19" order="sequential"/></sequence>
<sequence name="Slashed"><compute><result><replace from="-" to="/"><field name="D"/></replace></result></compute></sequence>
<sequence name="Bare"><compute><result><replace from="-" to=""><field name="D"/></replace></result></compute></sequence>
...
<data>${{D}} -> slash=${{Slashed}} | bare=${{Bare}}</data>
2020-05-14 -> slash=2020/05/14 | bare=20200514 2022-11-03 -> slash=2022/11/03 | bare=20221103 2020-01-30 -> slash=2020/01/30 | bare=20200130 2021-07-19 -> slash=2021/07/19 | bare=20210719
Заменяются оба дефиса, а не только первый. Чтобы заменять по позиции, а не по
подстроке, используйте <mask>.
<trim> — убрать крайние пробелы
Принимает одну строку → отдаёт строку. Трогаются только края; пробелы внутри остаются.
<trim> убирает пробелы с обоих краёв строки. Внутренние пробелы не трогает.
Атрибутов не имеет.
Когда применять: когда значения из файла или CSV несут лишние пробелы по краям. Здесь пробелы добавлены нарочно (имитируя «грязные» исходные данные), а скобки делают их видимыми:
<sequence name="City"><gen type="text" value="Moscow,Berlin,Paris" order="sequential"/></sequence>
<sequence name="Padded">
<compute><result><concat><str v=" "/><field name="City"/><str v=" "/></concat></result></compute>
</sequence>
<sequence name="Clean">
<compute><result><trim><field name="Padded"/></trim></result></compute>
</sequence>
...
<data>[${{Padded}}] -> [${{Clean}}]</data>
[ Moscow ] -> [Moscow] [ Berlin ] -> [Berlin] [ Paris ] -> [Paris]
<group> — сгруппировать символы справа
Принимает одну строку плюс size= и sep= → отдаёт строку. Группировка идёт справа налево, поэтому короткая группа оказывается слева — как пишут деньги.
<group size="…" sep="…"> разбивает строку на группы по size символов и
вставляет sep между ними. Группировка идёт справа налево, поэтому короткая
(неполная) группа оказывается слева, ровно как разделитель разрядов тысяч.
Строка короче одной группы возвращается без изменений (разделитель не добавляется).
| Атрибут | Обязателен | По умолчанию | Задаёт |
|---|---|---|---|
size | нет | 3 | размер группы (в символах) |
sep | нет | пробел " " | разделитель между группами |
Когда применять: когда длинное число нечитаемо — разряды тысяч, блоки карты, длинные коды:
<sequence name="N"><gen type="text" value="1234567,42,1000000,89150000" order="sequential"/></sequence>
<sequence name="G3"><compute><result><group size="3"><field name="N"/></group></result></compute></sequence>
<sequence name="G3d"><compute><result><group size="3" sep="-"><field name="N"/></group></result></compute></sequence>
<sequence name="G4"><compute><result><group size="4"><field name="N"/></group></result></compute></sequence>
...
<data>${{N}} -> group3=${{G3}} | group3,-=${{G3d}} | group4=${{G4}}</data>
1234567 -> group3=1 234 567 | group3,-=1-234-567 | group4=123 4567 42 -> group3=42 | group3,-=42 | group4=42 1000000 -> group3=1 000 000 | group3,-=1-000-000 | group4=100 0000 89150000 -> group3=89 150 000 | group3,-=89-150-000 | group4=8915 0000
Поскольку группировка идёт справа, 1234567 разбивается как 1 234 567 —
остаток 1 остаётся слева. group size="3" даёт разряды тысяч (разделитель по
умолчанию — пробел), sep="-" задаёт свой разделитель, size="4" читается как
блоки карты. Короткое 42 меньше одной группы, поэтому возвращается как есть.
Чтобы группировать слева или по позиции, используйте <mask>.
<pad> — дополнить слева до фиксированной ширины
Принимает одно значение плюс width= и fill= → отдаёт строку. width — это минимум: значение такой длины или длиннее проходит нетронутым, обрезки не бывает.
<pad width="…" fill="…"> приводит ребёнка к строке и дописывает fill слева,
пока строка не достигнет width. Ведёт себя как padStart: если строка уже не
короче width, она возвращается без изменений — обрезки нет.
| Атрибут | По умолчанию | Задаёт |
|---|---|---|
width | — | целевая ширина строки |
fill | "0" | символ, дописываемый слева |
Когда применять: когда идентификатору нужна фиксированная ширина — контрольный
номер, код артикула, контрольная цифра, которая должна занимать два места (09).
Ведущие нули до ширины 6:
<sequence name="Id"><gen type="number" value="1..9999"/></sequence>
<sequence name="Padded"><compute><result><pad width="6"><field name="Id"/></pad></result></compute></sequence>
...
<data>${{Id}} -> ${{Padded}}</data>
1401 -> 001401 3593 -> 003593 7646 -> 007646 6755 -> 006755 4701 -> 004701
fill может быть любым символом, а значение длиннее width не трогается:
<sequence name="P1"><compute><result><pad width="6"><str v="42"/></pad></result></compute></sequence>
<sequence name="P2"><compute><result><pad width="6" fill="*"><str v="42"/></pad></result></compute></sequence>
<sequence name="P3"><compute><result><pad width="4"><str v="1234567"/></pad></result></compute></sequence>
...
<data>zero=${{P1}} | fill*=${{P2}} | over=${{P3}}</data>
zero=000042 | fill*=****42 | over=1234567
"42" дополняется до ширины 6 нулями или звёздочками; "1234567" уже длиннее 4,
поэтому проходит насквозь — без обрезки. В отличие от mask / case / slice
/ group, у <pad> нет формы фильтра и нет атрибута <gen> — он работает
только как тег compute.
Одно поведение — три способа
Форматирование доступно как тег compute, атрибут <gen>
(mask= / case=) и фильтр в интерполяции (${{X | mask:…}}) — результат
одинаковый. Руководство Маски и регистр показывает
каждый способ с настоящим выводом. Где какие теги живут:
| Операция | Фильтр ${{X|…}} | Атрибут <gen> | Тег <compute> |
|---|---|---|---|
регистр (upper…title) | да | case= | <upper> … |
mask | да | mask= | <mask> |
slice / replace / trim / group | да | — | <slice> … |
concat / str / pad | — | — | эта страница (только compute) |
Берите тег compute, когда форматирование — звено вычисления; берите атрибут или фильтр для простого значения.
См. также
- Маски и регистр — те же операции, что и
фильтры
${{X|…}}и атрибуты<gen>, с готовым выводом. - Обзор compute — как
<compute>,<let>и<field>работают вместе. - Арифметика —
<to_number>/<encode>, чтобы перейти от текста к числам. - Списки и перебор —
<join>, чтобы превратить список в строку перед<concat>.