Xstring en
Xstring en
v1.83
User’s manual
Christian Tellechea
[email protected]
6 February 2019
Abstract
This package which requires ε-TEX, provides macros manipulating strings of tokens. For a basic use,
tokens can be alphanumeric chars, but the macros can also be useful for manipulating tokens, i.e. TEX
code. Main features are:
▷ tests:
– does a string contains at least n times an another?
– does a string starts (or ends) with another? etc.
– is a string an integer? A decimal?
– are 2 strings equal?
▷ extractions of substrings:
– what is on the left (or the right) of the nth occurrence of a substring;
– what is between the occurrences of 2 substrings;
– substring between 2 positions;
– serach of a group with its identifier.
▷ substitution of all, or the n first occurrences of a substring for an other substring;
▷ calculation of numbers:
– length of a string;
– position of the nth occurrence of a substring;
– how many times a string contains a substring?
– comparison of 2 strings: position of the first difference;
– identifier of the group in which a macro made a cut or a search.
Other macros allow to use special characters forbiden in arguments (# and %) and manage differences
between catcodes for advanced programming purposes.
Contents
1 Presentation 2
1.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2 The macros 2
2.1 The tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.1 \IfSubStr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.2 \IfSubStrBefore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.3 \IfSubStrBehind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1.4 \IfBeginWith . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.5 \IfEndWith . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.6 \IfInteger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.7 \IfDecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.8 \IfStrEq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.9 \IfEq . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.10 \IfStrEqCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.11 \IfEqCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2 Extraction of substrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.1 \StrBefore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.2 \StrBehind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.2.3 \StrCut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.4 \StrBetween . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.5 \StrSubstitute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.6 \StrDel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.7 \StrGobbleLeft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.8 \StrLeft . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.9 \StrGobbleRight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.10 \StrRight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.11 \StrChar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.12 \StrMid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Macros returning a number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.1 \StrLen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.2 \StrCount . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.3 \StrPosition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.4 \StrCompare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Operating modes 11
3.1 Expansion of arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1.1 The commands \fullexpandarg, \expandarg and \noexpandarg . . . . . . . . . . . . . . . . . 11
3.1.2 Chars and tokens allowed in arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Expansion of macros, optional argument . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3 How does xstring read the arguments? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3.1 Syntax unit by syntax unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3.2 Exploration of groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.4 Catcode and starred macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1
4.8.6 Example 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
This manual is a translation of the french manual. I apologize for my poor english but I did my best1 , and I hope that the
following is comprehensible!
1 Presentation
1.1 Description
This extension2 provides macros and tests operating on ”strings of tokens”, as other programmation languages have. They
provides the usual strings operations, such as: test if a string contains another, begins or ends with another, extractions
of strings, calculation of the position of a substring, of the number of occurrences, etc.
A ”string of tokens” is a list of tokens of any nature, except that braces must be balanced and tokens catcode 6 and 14
(usualy % et #) are not allowed. Apart from this, any token is allowed (including \par), in any order in the list, whatever
be the resulting code.
xstring reads the arguments of the macros syntax unit by syntax unit3 : when syntax units are ”simple” chars (catcode 10,
11 and 12), xstring logically read the argument char by char. xstring can also be used for programming purpose, including
in arguments other tokens such as control sequences, braces and tokens with other catcodes. See chapter on reading
mode and arguments expansion (page 13), the command \verbtocs (page 17) and the command \scancs (page 18).
As the arguments may contain any token, advanced users could have problems with catcodes leading to unexpected
behaviours. These behaviours can be controlled: read page 14.
Certainly, other packages exist (for example substr and stringstrings), but as well as differences on features, they do
not take into account occurrences so I found them too limited and difficult to use for programming.
1.2 Motivation
I decided to write this package of macros because I have never really found tools in LATEX suiting my needs for strings.
So, over the last few months, I wrote a few macros that I occasionally or regularly used. Their numbers have increased
and become a little too dispersed in directories in my computer, so I have grouped them together in this package.
Thus, writing a coherent set of macros forces more discipline and leads to necessary improvements, which took most of
the time I spent writing this package. This package is my first one as I recently discoverd LATEX4 , so my main motivation
was to make progress in programming with TEX, and to tackle its specific methods.
2 The macros
For a better understanding, let’s see first the macros with the simpler arguments possible. No special catcode, no exotic
token, no control sequence neither: only alphanumeric chars will be contained in the arguments.
In the following chapters, all the macros will be presented this plan:
• the syntax5 and the value of optional arguments
Important: in the following, a ⟨number⟩ can be an integer written with numeric chars, a counter, or the result of an
arithmetic operation made with the command \numexpr.
All the macros of xstring are displayed in red.
argument.
6 For much more examples, see the test file.
2
2.1 The tests
2.1.1 \IfSubStr
\IfSubStr⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
The value of the optional argument ⟨number⟩ is 1 by default.
Tests if ⟨string⟩ contains at least ⟨number⟩ times ⟨stringA⟩ and runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfSubStr{xstring}{tri}{true}{false} true
2 \IfSubStr{xstring}{a}{true}{false} false
3 \IfSubStr{a bc def }{c d}{true}{false} true
4 \IfSubStr{a bc def }{cd}{true}{false} false
5 \IfSubStr[2]{1a2a3a}{a}{true}{false} true
6 \IfSubStr[3]{1a2a3a}{a}{true}{false} true
7 \IfSubStr[4]{1a2a3a}{a}{true}{false} false
2.1.2 \IfSubStrBefore
\IfSubStrBefore⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
The values of the optional arguments ⟨number1⟩ and ⟨number2⟩ are 1 by default.
In ⟨string⟩, tests if the ⟨number1⟩th occurrence of ⟨stringA⟩ is on the left of the ⟨number2⟩th occurrence of ⟨stringB⟩. Runs
⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfSubStrBefore{xstring}{st}{in}{true}{false} true
2 \IfSubStrBefore{xstring}{ri}{s}{true}{false} false
3 \IfSubStrBefore{LaTeX}{LaT}{TeX}{true}{false} false
4 \IfSubStrBefore{a bc def }{ b}{ef}{true}{false} true
5 \IfSubStrBefore{a bc def }{ab}{ef}{true}{false} false
6 \IfSubStrBefore[2,1]{b1b2b3}{b}{2}{true}{false} true
7 \IfSubStrBefore[3,1]{b1b2b3}{b}{2}{true}{false} false
8 \IfSubStrBefore[2,2]{baobab}{a}{b}{true}{false} false
9 \IfSubStrBefore[2,3]{baobab}{a}{b}{true}{false} true
2.1.3 \IfSubStrBehind
\IfSubStrBehind⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
The values of the optional arguments ⟨number1⟩ and ⟨number2⟩ are 1 by default.
In ⟨string⟩, tests if the ⟨number1⟩th occurrence of ⟨stringA⟩ is on the right of the ⟨number2⟩th occurrence of ⟨stringB⟩.
Runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfSubStrBehind{xstring}{ri}{xs}{true}{false} false
2 \IfSubStrBehind{xstring}{s}{i}{true}{false} false
3 \IfSubStrBehind{LaTeX}{TeX}{LaT}{true}{false} false
4 \IfSubStrBehind{a bc def }{ d}{a}{true}{false} false
5 \IfSubStrBehind{a bc def }{cd}{a b}{true}{false} false
6 \IfSubStrBehind[2,1]{b1b2b3}{b}{2}{true}{false} false
7 \IfSubStrBehind[3,1]{b1b2b3}{b}{2}{true}{false} true
8 \IfSubStrBehind[2,2]{baobab}{b}{a}{true}{false} false
9 \IfSubStrBehind[2,3]{baobab}{b}{a}{true}{false} false
3
2.1.4 \IfBeginWith
\IfBeginWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
Tests if ⟨string⟩ begins with ⟨stringA⟩, and runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfBeginWith{xstring}{xst}{true}{false} true
2 \IfBeginWith{LaTeX}{a}{true}{false} false
3 \IfBeginWith{a bc def }{a b}{true}{false} true
4 \IfBeginWith{a bc def }{ab}{true}{false} false
2.1.5 \IfEndWith
\IfEndWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨Behind⟩}{⟨false⟩}
Tests if ⟨string⟩ ends with ⟨stringA⟩, and runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfEndWith{xstring}{ring}{true}{false} true
2 \IfEndWith{LaTeX}{a}{true}{false} false
3 \IfEndWith{a bc def }{ef }{true}{false} true
4 \IfEndWith{a bc def }{ef}{true}{false} false
2.1.6 \IfInteger
\IfInteger{⟨number⟩}{⟨true⟩}{⟨false⟩}
Tests if ⟨number⟩ is an integer (i.e whose decimal part is empty or 0), and runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
If test is false because unexpected characters, the control sequence \@xs@afterinteger and \afterinteger both con-
tain the illegal part of ⟨number⟩.
1 \IfInteger{13}{true}{false} true
2 \IfInteger{-219}{true}{false} true
3 \IfInteger{+9}{true}{false} true
4 \IfInteger{3.14}{true}{false} false
5 \IfInteger{8.0}{true}{false} true
6 \IfInteger{0}{true}{false} true
7 \IfInteger{49a}{true}{false} false
8 \IfInteger{+}{true}{false} false
9 \IfInteger{-}{true}{false} false
10 \IfInteger{0000}{true}{false} true
2.1.7 \IfDecimal
\IfDecimal{⟨number⟩}{⟨true⟩}{⟨false⟩}
Tests if ⟨number⟩ is a decimal, and runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
Counters \integerpart and \decimalpart contain the integer part and decimal part of ⟨number⟩.
If test is false because unexpected characters, the control sequence \@xs@afterdecimal and \afterdecimal both con-
tain the illegal part of ⟨number⟩, whereas if test is false because decimal part is empty after decimal separator, they contain
”X”.
4
1 \IfDecimal{3.14}{true}{false} true
2 \IfDecimal{3,14}{true}{false} true
3 \IfDecimal{-0.5}{true}{false} true
4 \IfDecimal{.7}{true}{false} true
5 \IfDecimal{,9}{true}{false} true
6 \IfDecimal{1..2}{true}{false} false
7 \IfDecimal{+6}{true}{false} true
8 \IfDecimal{-15}{true}{false} true
9 \IfDecimal{1.}{true}{false} false
10 \IfDecimal{2,}{true}{false} false
11 \IfDecimal{.}{true}{false} false
12 \IfDecimal{,}{true}{false} false
13 \IfDecimal{+}{true}{false} false
14 \IfDecimal{-}{true}{false} false
2.1.8 \IfStrEq
\IfStrEq⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
Tests if the strings ⟨stringA⟩ and ⟨stringB⟩ are equal, i.e. if they contain successively the same syntax units in the same
order. Runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
1 \IfStrEq{a1b2c3}{a1b2c3}{true}{false} true
2 \IfStrEq{abcdef}{abcd}{true}{false} false
3 \IfStrEq{abc}{abcdef}{true}{false} false
4 \IfStrEq{3,14}{3,14}{true}{false} true
5 \IfStrEq{12.34}{12.340}{true}{false} false
6 \IfStrEq{abc}{}{true}{false} false
7 \IfStrEq{}{abc}{true}{false} false
8 \IfStrEq{}{}{true}{false} true
2.1.9 \IfEq
\IfEq{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
Tests if the strings ⟨stringA⟩ and ⟨stringB⟩ are equal, except if both ⟨stringA⟩ and ⟨stringB⟩ contain numbers in which case
the macro tests if these numbers are equal. Runs ⟨true⟩ if so, and ⟨false⟩ otherwise.
▷ The definition of number is given with the macro \IfDecimal (see page 4), and thus :
▷ ”+” signs are optional;
▷ Decimal separator can be a dot or a comma.
1 \IfEq{a1b2c3}{a1b2c3}{true}{false} true
2 \IfEq{abcdef}{ab}{true}{false} false
3 \IfEq{ab}{abcdef}{true}{false} false
4 \IfEq{12.34}{12,34}{true}{false} true
5 \IfEq{+12.34}{12.340}{true}{false} true
6 \IfEq{10}{+10}{true}{false} true
7 \IfEq{-10}{10}{true}{false} false
8 \IfEq{+0,5}{,5}{true}{false} true
9 \IfEq{1.001}{1.01}{true}{false} false
10 \IfEq{3*4+2}{14}{true}{false} false
11 \IfEq{\number\numexpr3*4+2}{14}{true}{false} true
12 \IfEq{0}{-0.0}{true}{false} true
13 \IfEq{}{}{true}{false} true
2.1.10 \IfStrEqCase
\IfStrEqCase⟨[*]⟩{⟨string⟩}{%
{⟨string1⟩}{⟨code1⟩}%
{⟨string2⟩}{⟨code2⟩}%
etc...
{⟨stringN ⟩}{⟨codeN ⟩}}[⟨other cases code⟩]
5
Tests successively if ⟨string⟩ is equal to ⟨string1⟩, ⟨string2⟩, etc. Comparison is made with \IfStrEq (see above). If the
test number i is positive (the ⟨string⟩ matches ⟨string i⟩), the macro runs ⟨code i⟩ and ends. If all tests fail, the macro runs
the optional ⟨other cases code⟩, if present.
1 \IfStrEqCase{b}{{a}{AA}{b}{BB}{c}{CC}} BB
2 |\IfStrEqCase{abc}{{a}{AA}{b}{BB}{c}{CC}}| ||
3 \IfStrEqCase{c}{{a}{AA}{b}{BB}{c}{CC}}[other] CC
4 \IfStrEqCase{d}{{a}{AA}{b}{BB}{c}{CC}}[other] other
5 \IfStrEqCase{+3}{{1}{one}{2}{two}{3}{three}}[other] other
6 \IfStrEqCase{0.5}{{0}{zero}{.5}{half}{1}{one}}[other] other
2.1.11 \IfEqCase
\IfEqCase⟨[*]⟩{⟨string⟩}{%
{⟨string1⟩}{⟨code1⟩}%
{⟨string2⟩}{⟨code2⟩}%
etc...
{⟨stringN ⟩}{⟨codeN ⟩}}[⟨other cases code⟩]
Tests successively if ⟨string⟩ is equal to ⟨string1⟩, ⟨string2⟩, etc. Comparison is made with \IEq (see above). If the test
number i is positive (the ⟨string⟩ matches ⟨string i⟩), the macro runs ⟨code i⟩ and ends. If all tests fail, the macro runs the
optional ⟨other cases code⟩, if present.
1 \IfEqCase{b}{{a}{AA}{b}{BB}{c}{CC}} BB
2 |\IfEqCase{abc}{{a}{AA}{b}{BB}{c}{CC}}| ||
3 \IfEqCase{c}{{a}{AA}{b}{BB}{c}{CC}}[other] CC
4 \IfEqCase{d}{{a}{AA}{b}{BB}{c}{CC}}[other] other
5 \IfEqCase{+3}{{1}{one}{2}{two}{3}{three}}[other] three
6 \IfEqCase{0.5}{{0}{zero}{.5}{half}{1}{one}}[other] half
\StrBefore⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
The value of the optional argument ⟨number⟩ is 1 by default.
In ⟨string⟩, returns what is leftwards the ⟨number⟩th occurrence of ⟨stringA⟩.
1 \StrBefore{xstring}{tri} xs
2 \StrBefore{LaTeX}{e} LaT
3 |\StrBefore{LaTeX}{p}| ||
4 |\StrBefore{LaTeX}{L}| ||
5 |\StrBefore{a bc def }{def}| |a bc |
6 |\StrBefore{a bc def }{cd}| ||
7 \StrBefore[1]{1b2b3}{b} 1
8 \StrBefore[2]{1b2b3}{b} 1b2
2.2.2 \StrBehind
\StrBehind⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
The value of the optional argument ⟨number⟩ is 1 by default.
In ⟨string⟩, returns what is rightwards the ⟨number⟩th occurrence of ⟨stringA⟩.
6
▷ If ⟨number⟩ < 1 then the macro behaves as if ⟨number⟩ = 1;
▷ If the occurrence is not found, an empty string is returned.
1 \StrBehind{xstring}{tri} ng
2 \StrBehind{LaTeX}{e} X
3 |\StrBehind{LaTeX}{p}| ||
4 |\StrBehind{LaTeX}{X}| ||
5 |\StrBehind{a bc def }{bc}| | def |
6 |\StrBehind{a bc def }{cd}| ||
7 \StrBehind[1]{1b2b3}{b} 2b3
8 \StrBehind[2]{1b2b3}{b} 3
9 |\StrBehind[3]{1b2b3}{b}| ||
2.2.3 \StrCut
2.2.4 \StrBetween
\StrBetween⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
The values of the optional arguments ⟨number1⟩ and ⟨number2⟩ are 1 by default.
In ⟨string⟩, returns the substring between7 the ⟨number1⟩th occurrence of ⟨stringA⟩ and ⟨number2⟩th occurrence of ⟨stringB⟩.
▷ If the occurrences are not in this order — ⟨stringA⟩ followed by ⟨stringB⟩ — in ⟨string⟩, an empty string is returned;
▷ If one of the 2 occurrences doesn’t exist in ⟨string⟩, an empty string is returned;
▷ If one of the optional arguments ⟨number1⟩ ou ⟨number2⟩ is negative or zero, an empty string is returned.
1 \StrBetween{xstring}{xs}{ng} tri
2 |\StrBetween{xstring}{i}{n}| ||
3 |\StrBetween{xstring}{a}{tring}| ||
4 |\StrBetween{a bc def }{a}{d}| | bc |
5 |\StrBetween{a bc def }{a }{f}| |bc de|
6 \StrBetween{a1b1a2b2a3b3}{a}{b} 1
7 \StrBetween[2,3]{a1b1a2b2a3b3}{a}{b} 2b2a3
8 \StrBetween[1,3]{a1b1a2b2a3b3}{a}{b} 1b1a2b2a3
9 |\StrBetween[3,1]{a1b1a2b2a3b3}{a}{b}| ||
10 \StrBetween[3,2]{abracadabra}{a}{bra} da
7
2.2.5 \StrSubstitute
\StrSubstitute[⟨number⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
The value of the optional argument ⟨number⟩ is 0 by default.
In ⟨string⟩, substitute the ⟨number⟩ first occurrences of ⟨stringA⟩ for ⟨stringB⟩, except if ⟨number⟩ = 0 in which case all
the occurrences are substituted.
▷ If ⟨string⟩ is empty, an empty string is returned;
▷ If ⟨stringA⟩ is empty or doesn’t exist in ⟨string⟩, the macro is ineffective;
▷ If ⟨number⟩ is greater than the number of occurrences of ⟨stringA⟩, then all the occurrences are substituted;
▷ If ⟨number⟩ < 0 the macro behaves as if ⟨number⟩ = 0;
▷ If ⟨stringB⟩ is empty, the occurrences of ⟨stringA⟩, if they exist, are deleted.
1 \StrSubstitute{xstring}{i}{a} xstrang
2 \StrSubstitute{abracadabra}{a}{o} obrocodobro
3 \StrSubstitute{abracadabra}{br}{TeX} aTeXacadaTeXa
4 \StrSubstitute{LaTeX}{m}{n} LaTeX
5 \StrSubstitute{a bc def }{ }{M} aMbcMdefM
6 \StrSubstitute{a bc def }{ab}{AB} a bc def
7 \StrSubstitute[1]{a1a2a3}{a}{B} B1a2a3
8 \StrSubstitute[2]{a1a2a3}{a}{B} B1B2a3
9 \StrSubstitute[3]{a1a2a3}{a}{B} B1B2B3
10 \StrSubstitute[4]{a1a2a3}{a}{B} B1B2B3
2.2.6 \StrDel
\StrDel⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
The value of the optional argument ⟨number⟩ is 0 by default.
Delete the ⟨number⟩ first occurrences of ⟨stringA⟩ in ⟨string⟩, except if ⟨number⟩ = 0 in which case all the occurrences
are deleted.
1 \StrDel{abracadabra}{a} brcdbr
2 \StrDel[1]{abracadabra}{a} bracadabra
3 \StrDel[4]{abracadabra}{a} brcdbra
4 \StrDel[9]{abracadabra}{a} brcdbr
5 \StrDel{a bc def }{ } abcdef
6 |\StrDel{a bc def }{def}| |a bc |
2.2.7 \StrGobbleLeft
\StrGobbleLeft{⟨string⟩}{⟨number⟩}[⟨name⟩]
In ⟨string⟩, delete the ⟨number⟩ first characters on the left.
1 \StrGobbleLeft{xstring}{2} tring
2 |\StrGobbleLeft{xstring}{9}| ||
3 \StrGobbleLeft{LaTeX}{4} X
4 \StrGobbleLeft{LaTeX}{-2} LaTeX
5 |\StrGobbleLeft{a bc def }{4}| | def |
8
2.2.8 \StrLeft
\StrLeft{⟨string⟩}{⟨number⟩}[⟨name⟩]
In ⟨string⟩, returns the ⟨number⟩ first characters on the left.
1 \StrLeft{xstring}{2} xs
2 \StrLeft{xstring}{9} xstring
3 \StrLeft{LaTeX}{4} LaTe
4 |\StrLeft{LaTeX}{-2}| ||
5 |\StrLeft{a bc def }{5}| |a bc |
2.2.9 \StrGobbleRight
\StrGobbleRight{⟨string⟩}{⟨number⟩}[⟨name⟩]
In ⟨string⟩, delete the ⟨number⟩ last characters on the right.
1 \StrGobbleRight{xstring}{2} xstri
2 |\StrGobbleRight{xstring}{9}| ||
3 \StrGobbleRight{LaTeX}{4} L
4 |\StrGobbleRight{LaTeX}{-2}| |LaTeX|
5 |\StrGobbleRight{a bc def }{4}| |a bc |
2.2.10 \StrRight
\StrRight{⟨string⟩}{⟨number⟩}[⟨name⟩]
In ⟨string⟩, returns the ⟨number⟩ last characters on the right.
1 \StrRight{xstring}{2} ng
2 \StrRight{xstring}{9} xstring
3 \StrRight{LaTeX}{4} aTeX
4 |\StrRight{LaTeX}{-2}| ||
5 \StrRight{a bc def }{5} def
2.2.11 \StrChar
\StrChar⟨[*]⟩{⟨string⟩}{⟨number⟩}[⟨name⟩]
Returns the syntax unit at the position ⟨number⟩ in ⟨string⟩.
1 \StrChar{xstring}{4} r
2 |\StrChar{xstring}{9}| ||
3 |\StrChar{xstring}{-5}| ||
4 \StrChar{a bc def }{6} d
2.2.12 \StrMid
\StrMid{⟨string⟩}{⟨numberA⟩}{⟨numberB⟩}[⟨name⟩]
In ⟨string⟩, returns the substring between8 the positions ⟨numberA⟩ and ⟨numberB⟩.
9
▷ If ⟨numberA⟩ > ⟨numberB⟩, an empty string is returned;
▷ If ⟨numberA⟩ < 1 and ⟨numberB⟩ < 1 an empty string is returned;
▷ If ⟨numberA⟩ > ⟨lengthString⟩ et ⟨numberB⟩ > ⟨lengthString⟩, an empty string is returned;
▷ If ⟨numberA⟩ < 1, the macro behaves as if ⟨numberA⟩ = 1;
▷ If ⟨numberB⟩ > ⟨lengthString⟩, the macro behaves as if ⟨numberB⟩ = ⟨lengthString⟩.
1 \StrMid{xstring}{2}{5} stri
2 \StrMid{xstring}{-4}{2} xs
3 |\StrMid{xstring}{5}{1}| ||
4 \StrMid{xstring}{6}{15} ng
5 \StrMid{xstring}{3}{3} t
6 |\StrMid{a bc def }{2}{7}| | bc de|
\StrLen{⟨string⟩}[⟨name⟩]
Return the length of ⟨string⟩.
1 \StrLen{xstring} 7
2 \StrLen{A} 1
3 \StrLen{a bc def } 9
2.3.2 \StrCount
\StrCount{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
Counts how many times ⟨stringA⟩ is contained in ⟨string⟩.
▷ If one at least of the arguments ⟨string⟩ or ⟨stringA⟩ is empty, the macro return 0.
1 \StrCount{abracadabra}{a} 5
2 \StrCount{abracadabra}{bra} 2
3 \StrCount{abracadabra}{tic} 0
4 \StrCount{aaaaaa}{aa} 3
2.3.3 \StrPosition
\StrPosition[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
The value of the optional argument ⟨number⟩ is 1 by default.
In ⟨string⟩, returns the position of the ⟨number⟩th occurrence of ⟨stringA⟩.
▷ If ⟨number⟩ is greater than the number of occurrences of ⟨stringA⟩, then the macro returns 0;
▷ If ⟨string⟩ doesn’t contain ⟨stringA⟩, then the macro returns 0.
1 \StrPosition{xstring}{ring} 4
2 \StrPosition[4]{abracadabra}{a} 8
3 \StrPosition[2]{abracadabra}{bra} 9
4 \StrPosition[9]{abracadabra}{a} 0
5 \StrPosition{abracadabra}{z} 0
6 \StrPosition{a bc def }{d} 6
7 \StrPosition[3]{aaaaaa}{aa} 5
10
2.3.4 \StrCompare
\StrCompare⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
This macro has 2 tolerances: the ”normal” tolerance, used by default, and the ”strict” tolerance.
• The normal tolerance is activated with \comparenormal.
The macro compares characters from left to right in ⟨stringA⟩ and ⟨stringB⟩ until a difference appears or the end
of the shortest string is reached. The position of the first difference is returned and if no difference is found, the
macro return 0.
• The strict tolerance is activated with \comparestrict.
The macro compares the 2 strings. If they are equal, it returns 0. If not, the position of the first difference is returned.
It is possible to save the comparison mode with \savecomparemode, then modify this comparison mode and come back
to the situation when it was saved with \restorecomparemode.
Examples with the normal tolerance:
1 \StrCompare{abcd}{abcd} 0
2 \StrCompare{abcd}{abc} 0
3 \StrCompare{abc}{abcd} 0
4 \StrCompare{a b c}{abc} 2
5 \StrCompare{aaa}{baaa} 1
6 \StrCompare{abc}{xyz} 1
7 \StrCompare{123456}{123457} 6
8 \StrCompare{abc}{} 0
1 \StrCompare{abcd}{abcd} 0
2 \StrCompare{abcd}{abc} 4
3 \StrCompare{abc}{abcd} 4
4 \StrCompare{a b c}{abc} 2
5 \StrCompare{aaa}{baaa} 1
6 \StrCompare{abc}{xyz} 1
7 \StrCompare{123456}{123457} 6
8 \StrCompare{abc}{} 1
3 Operating modes
3.1 Expansion of arguments
3.1.1 The commands \fullexpandarg, \expandarg and \noexpandarg
The command \fullexpandarg is called by default, so all the arguments are fully expanded (an \edef is used) before the
the macro works on them. In most of the cases, this expansion mode avoids chains of \expandafter and allows lighter
code.
Of course, the expansion of argument can be canceled to find back the usual behaviour of TEX with the commands \
noexpandarg or \normalexpandarg.
Another expansion mode can be called with \expandarg. In this case, the first token of each argument is expanded
one time while all other tokens are left unchanged (if you want the expansion of all tokens one time, you should call the
macro \StrExpand, see page 18).
The commands \fullexpandarg, \noexpandarg, \normalexpandarg and \expandarg can be called at any moment in
the code; they behave as ”switches” and they can be locally used in a group.
It is possible to save the expansion mode with \saveexpandmode, then modify this expansion mode and come back to
the situation when it was saved with \restoreexpandmode.
In the following list, for every macro of the previous chapter, the arguments colored in purple will possibly be expanded,
according to the expansion mode:
• \IfSubStr⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
11
• \IfSubStrBefore⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfSubStrBehind⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfBeginWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
• \IfEndWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
• \IfInteger{⟨number⟩}{⟨true⟩}{⟨false⟩}
• \IfDecimal{⟨number⟩}{⟨true⟩}{⟨false⟩}
• \IfStrEq⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfEq⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfStrEqCase⟨[*]⟩{⟨string⟩}{{⟨string1⟩}{⟨code1⟩}
{⟨string2⟩}{⟨code2⟩}
…
{⟨string n⟩}{⟨code n⟩}}[⟨other cases code⟩]
• \IfEqCase⟨[*]⟩{⟨string⟩}{{⟨string1⟩}{⟨code1⟩}
{⟨string2⟩}{⟨code2⟩}
…
{⟨string n⟩}{⟨code n⟩}}[⟨other cases code⟩]
• \StrBefore⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrBehind⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrBetween⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
• \StrSubstitute[⟨number⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
• \StrDel[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrSplit{⟨string⟩}{⟨number⟩}{⟨stringA⟩}{⟨stringB⟩} (see macro StrSplit page 17)
• \StrGobbleLeft{⟨string⟩}{⟨number⟩}[⟨name⟩]
• \StrLeft{⟨string⟩}{⟨number⟩}[⟨name⟩]
• \StrGobbleRight{⟨string⟩}{⟨number⟩}[⟨name⟩]
• \StrRight{⟨string⟩}{⟨number⟩}[⟨name⟩]
• \StrChar{⟨string⟩}{⟨number⟩}[⟨name⟩]
• \StrMid{⟨string⟩}{⟨number1⟩}{⟨number2⟩}[⟨name⟩]
• \StrLen{⟨string⟩}[⟨name⟩]
• \StrCount{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrPosition[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrCompare{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
12
3.1.2 Chars and tokens allowed in arguments
First of all, whatever be the current expansion mode, tokens with catcode 6 and 14 (usually # and %) are forbidden
in all the arguments9 .
When full expansion mode is activated with \fullexpandarg, arguments are expanded with an \edef before they are
read by the macro. Consequently, are allowed in arguments:
• letters (uppercase or lowercase, accented10 or not), figures, spaces, and any other character with a catcode of 10, 11
ou 12 (punctuation signs, calculation signs, parenthesis, square bracket, etc).;
• tokens with catcode 1 to 4, usually : { }11 $ &
When arguments are not expanded with the use of \noexpandarg, other tokens can be put in a string whatever be the
code they make: any control sequence, even undefined, any token catcode 13. Moreover, test tokens are allowed like \if
or \ifx, even without their \fi. On the same way, a \csname without its \endcsname is allowed.
In this example, the argument contains a \ifx without the \fi: the \StrBetween command extracts and dislpays what
is between \ifx and \else:
1 \noexpandarg
ab false
2 \StrBetween{\ifx ab false \else true}{\ifx}{\else}
When \expandarg is used, the first token needs precaution since it is expanded one time: it must be defined. The other
tokens are left unchanged like with \noexpandarg.
And this nested structure, not allowed neither, supposed to remove the first and last char of xstring:
\StrGobbleLeft{\StrGobbleRight{xstring}{1}}{1}
should be written like this:
\StrGobbleRight{xstring}{1}[\mystring]
\StrGobbleleft{\mystring}{1}
13
• a char.
Let’s see what is a syntax unit with an example. Let’s take this argument : ”ab\textbf{xyz}cd”
It has 6 syntax units: ”a”, ”b”, ”\textbf”, ”{xyz}”, ”c” and ”d”.
What will happen if, while \noexpandarg is active, we ask xstring to find the length of this argument and find its 4th
”char”
1 \noexpandarg
2 \StrLen{ab\textbf{xyz}cd}\par 6
3 \StrChar{ab\textbf{xyz}cd}{4}[\mychar] macro:->{xyz}
4 \meaning\mychar
It is necessary to use \meaning to see the real expansion of \mychar, and not simply call \mychar to display it, which
make loose informations (braces here). We do not obtain a ”char” but a syntax unit, as expected.
1 \noexpandarg
2 \exploregroups
8
3 \StrLen{ab\textbf{xyz}cd}\par
macro:->x
4 \StrChar{ab\textbf{xyz}cd}{4}[\mychar]
5 \meaning\mychar
Exploring the groups can be usefull for counting a substring in a string (\StrCount), for the position of a substring in a
string (\StrPosition) or for tests, but has a severe limitation with macros returning a string: when a string is cut inside
a group, the result does not take into account what is outside this group. This exploration mode must be used
knowingly this limitation when calling macros returning a string.
Let’s see what this means with an example. We want to know what is on the left of the second appearance of \a in the
argument \a1{\b1\a2}\a3. As groups are explored, this appearance is inside this group : {\b1\a2}. The result will be
\b1. Let’s check:
1 \noexpandarg
2 \exploregroups
macro:->\b 1
3 \StrBefore[2]{\a1{\b1\a2}\a3}{\a}[\mycs]
4 \meaning\mycs
Exploring the groups14 can change the behaviour of most of the macros of xstring, excepted these macros untouched
by the exploration mode; their behaviour is the same in any case: \IfInteger, \IfDecimal, \IfStrEq, \StrEq et \
StrCompare.
Moreover, 2 macros run in \noexploregroups mode, whatever be the current mode: \StrBetween et \StrMid.
It is possible to save the exploration mode with \saveexploremode, then modify it and come back to the situation when
it was saved with \restoreexploremode.
14 The file test of xstring has many examples underlining differences between exploration modes.
14
do not expand into equal strings for xstring! Because of the command \string, the first expands into ”ab” with catcodes
12 while the second have characters with their natural catcodes 11. Catcodes do not match! It is necessary to be aware
of this, particulary with TEX commands like \string whose expansions are a strings with chars catcodes 12 and 10 :
\detokenize, \meaning, \jobname, \fontname, \romannumeral, etc.
Starred macros do not take catcodes into account. They simply convert some arguments into arguments with catcodes
10, 11 and 12, and call the non-starred macros with these modified arguments. The optional arguments are not modified
and the catcodes are left unchanged.
Here is an example:
The strings do not match because of catcode differences: the test is negative in the non-starred macro.
Warning: the use of a strarred macro has consequences! The arguments are ”detokenized”, thus, there is no more control
sequences, groups, neither any special char: everything is converted into chars with ”harmless” catcodes.
For the macros returning a string, if the starred version is used, the result will be a string in which chars have catcodes 12
and 10 for space. For example, after a ”\StrBefore*{a \b c d}{c}[\mytext]”, the control sequence \mytext expands
to ”a12 ␣10 \12 b12 ␣10 ”.
The macro with a starred version are listed below. For these macros, if starred version is used, the purple arguments will
be detokenized:
• \IfSubStr⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
• \IfSubStrBefore⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfSubStrBehind⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfBeginWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
• \IfEndWith⟨[*]⟩{⟨string⟩}{⟨stringA⟩}{⟨true⟩}{⟨false⟩}
• \IfStrEq⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfEq⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}{⟨true⟩}{⟨false⟩}
• \IfStrEqCase⟨[*]⟩{⟨string⟩}{{⟨string1⟩}{⟨code1⟩}
{⟨string2⟩}{⟨code2⟩}
…
{⟨string n⟩}{⟨code n⟩}}[⟨other cases code⟩]
• \IfEqCase⟨[*]⟩{⟨string⟩}{{⟨string1⟩}{⟨code1⟩}
{⟨string2⟩}{⟨code2⟩}
…
{⟨string n⟩}{⟨code n⟩}}[⟨other cases code⟩]
• \StrBefore⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrBehind⟨[*]⟩[⟨number⟩]{⟨string⟩}{⟨stringA⟩}[⟨name⟩]
• \StrBetween⟨[*]⟩[⟨number1⟩,⟨number2⟩]{⟨string⟩}{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
• \StrCompare⟨[*]⟩{⟨stringA⟩}{⟨stringB⟩}[⟨name⟩]
15
4.1 Finding a group, macros \StrFindGroup and \groupID
When \exploregroups mode is active, the macro \StrFindGroup finds a group between braces with its identifier:
\StrFindGroup{⟨argument⟩}{⟨identifier⟩}[⟨name⟩]
When the group matching the identifier does not exist, an empty string is assigned to ⟨name⟩. If the group is found, this
group with its braces is assigned to ⟨name⟩.
This identifier characterizes the nestling position of the group. It is a list of one or several integers separated with commas.
n1 , the first integer is the number of the group (not nestled in another) in which the sought group is. Inside this group,
the second integer n2 is the number of the group (not nestled in another) in which the sought group is…and so on until
the necessary nestling depth is reached to obtain the sougth after group.
Let’s take an example with 3 levels of nestled groups. In this example, braces delimiting groups are colored in red for
nestling level 1, in blue for level 2 and in green for level 3. The groups are numbered with the rule seen above:
In this example:
1 \exploregroups
2 \expandarg
3 \def\mystring{a{{bc}d{efg}}h{{ij}{k}{l{m}{no}}p}}
4 \StrFindGroup{\mystring}{1}[\mygroup]
5 \meaning\mygroup\par macro:->{{bc}d{efg}}
macro:->{ij}
6 \StrFindGroup{\mystring}{2,1}[\mygroup]
macro:->{no}
7 \meaning\mygroup\par macro:->
8 \StrFindGroup{\mystring}{2,3,2}[\mygroup]
9 \meaning\mygroup\par
10 \StrFindGroup{\mystring}{2,5}[\mygroup]
11 \meaning\mygroup\par
The reverse process exists, and several macros of xstring provide the identifier of the group in which they made a
cut or they found a substring. These macros are: \IfSubStr, \StrBefore, \StrBehind, \StrSplit, \StrLeft, \
StrGobbleLeft, \StrRight, \StrGobbleRight, \StrChar, \StrPosition.
After these macros, the control sequence \groupID expands to the identifier of the group where the cut has been done
or the search has succeeded. When not cut can be done or the search fails, \groupID is empty. Obvioulsly, the use of
\groupID has sense only when \exploregroups mode is acive and when non starred macros are used.
Here are some examples with the macro \StrChar:
1 \exploregroups
2 char 1 = \StrChar{a{b{cd}{e{f}g}h}ijkl}{1}\qquad
3 \string\groupID = \groupID\par
char 1 = a \groupID= 0
4 char 4 = \StrChar{a{b{cd}{e{f}g}h}ijkl}{4}\qquad
char 4 = d \groupID= 1,1
5 \string\groupID = \groupID\par
char 6 = f \groupID= 1,1,2,1
6 char 6 = \StrChar{a{b{cd}{e{f}g}h}ijkl}{6}\qquad char 20 = \groupID=
7 \string\groupID = \groupID\par
8 char 20 = \StrChar{a{b{cd}{e{f}g}h}ijkl}{20}\qquad
9 \string\groupID = \groupID
16
4.2 Splitting a string, the macro \StrSplit
Here is the syntax:
\StrSplit{⟨string⟩}{⟨number⟩}{⟨stringA⟩}{⟨stringB⟩}
The ⟨string⟩, is splitted after the syntax unit at position ⟨number⟩. The left part is assigned to the control sequence
⟨stringA⟩ and the right part is assigned to ⟨stringB⟩.
This macro returns two strings, so it does not display anything. Consequently, it does not provide the optional argument
in last position.
1 \def\redsep{{\color{red}|}}%
2 \StrSplit{abcdef}{4}{\csA}{\csB}|\csA\redsep\csB| |abcd|ef|
|a |b c |
3 \StrSplit{a b c }{2}{\csA}{\csB}|\csA\redsep\csB|
|a|bcdef|
4 \StrSplit{abcdef}{1}{\csA}{\csB}|\csA\redsep\csB|
|abcde|f|
5 \StrSplit{abcdef}{5}{\csA}{\csB}|\csA\redsep\csB| |abcdef||
6 \StrSplit{abcdef}{9}{\csA}{\csB}|\csA\redsep\csB| ||abcdef|
7 \StrSplit{abcdef}{-3}{\csA}{\csB}|\csA\redsep\csB|
When the exploration of groups is active and the cut is made at the end of a group, the content of the left string will tbe
the entire group while the right string will be empty. The example shows this:
1 \exploregroups
2 \StrSplit{ab{cd{ef}gh}ij}{6}\strA\strB macro:->ef
3 \meaning\strA\par macro:->
4 \meaning\strB
This macro provides a star version: in this case, the cut is made just before the syntax unit which follows the syntax unit
at position ⟨number⟩. Both version give same results, except when the cut is made at the end of a group; in that case,
\StrSplit closes as many group as necessary until it finds the next syntax unit: the cut is made just before this syntax
unit.
1 \exploregroups
2 Use without star :\par
Use without star :
3 \StrSplit{ab{cd{ef}gh}ij}{6}\strA\strB
macro:->ef
4 \meaning\strA\par
macro:->
5 \meaning\strB\par \groupID = 1,1
6 \string\groupID\ = \groupID\par\medskip
Use with star :
7 Use with star :\par
macro:->cd{ef}
8 \StrSplit*{ab{cd{ef}gh}ij}{6}\strA\strB
macro:->gh
9 \meaning\strA\par \groupID = 1,1
10 \meaning\strB\par
11 \string\groupID\ = \groupID
17
About verb arguments, keep in mind that:
• all the characters before |⟨characters⟩| are ignored;
• inside the verb argument, all the spaces are taken into account, even if they are consecutive.
Example:
Example:
1 \verbtocs{\text}|\textbf{a} $\frac{1}{2}$|
2 text : \text text : \textbf{a} $\frac{1}{2}$
3 \tokenize{\result}{\text}\par result : a 12
4 result : \result
Obviously, the control sequence \result can be called at the last line since the control sequences it contains are defined.
4.5 Expansion of a control sequence before verbatimize, the macros \StrExpand and
\scancs
The macro \StrExpand expands the tokens of a string:
\StrExpand[⟨number⟩]{⟨string⟩}{⟨name⟩}
By default, ⟨number⟩ is 1 and represnts the number of times each token of ⟨string⟩ has to be expanded. The ⟨name⟩ is a
control sequence receiving the result of the expansions.
Macro works sequentially and by pass: in a pass, each token from left to right is replaced by its 1-expansion. After this
expansion, if the ⟨number⟩ of expansions is not reached, an other pass starts, and so on.
Here is an example:
1 \def\csA{1 2}
2 \def\csB{a \csA}
3 \def\csC{\csB\space}
4 \def\csD{x{\csA y}\csB{\csC z}}
5 Expansion of \string\csD\ at\par
6 \StrExpand[0]{\csD}{\csE} depth 0 : Expansion of \csD at
depth 0 : \csD
7 \detokenize\expandafter{\csE}\par
depth 1 : x{\csA y}\csB {\csC z}
8 \StrExpand[1]{\csD}{\csE} depth 1 :
depth 2 : x{1 2y}a \csA {\csB \space z}
9 \detokenize\expandafter{\csE}\par depth 3 : x{1 2y}a 1 2{a \csA z}
10 \StrExpand[2]{\csD}{\csE} depth 2 : depth 4 : x{1 2y}a 1 2{a 1 2 z}
11 \detokenize\expandafter{\csE}\par
12 \StrExpand[3]{\csD}{\csE} depth 3 :
13 \detokenize\expandafter{\csE}\par
14 \StrExpand[4]{\csD}{\csE} depth 4 :
15 \detokenize\expandafter{\csE}
The macro expands each token consecutively, and does not see what follows: tokens whose expansion depends on other
tokens cannot be expanded with this macro. For instance, though ”\iftrue A\else B\fi” has a natural expansion (”A”),
it cannot be put in the argument of \StrExpand and:
\StrExpand{\iftrue A\else B\fi}\resultat
provokes an error because the first token ”\iftrue” is expanded alone without seeing its \fi which makes TEX angry.
18
Expansion inside groups is independant of the exploration mode: this macro has its own command to expand or not
what is inside the groups. By default, tokens inside groups are expanded, but this can be changed with the macro \
noexpandingroups. The default behaviour can be recoverd with \expandingroups.
It is forbidden to use the command \verb inside the definition of a macro. For the same reasons:
Do not use \verbtocs inside the definition of a macro.
But then, how to manipulate special characters and ”verbatimize” inside the définition of macros ?
It is better to use \scancs and define outside the definition of the macros control sequences containing special characters
with \verbtocs. It is also possible to use \tokenize to transform the final result (which is generaly text10,11,12 ) into
control sequences. See example using these macros at the end of this manual, page 20.
In the following teaching example16 , the macro \bracearg adds braces to its argument. To make this possible, 2 control
sequences \Ob and \Cb containing ”{” and ”}” are defined outside the definition of \bracearg, and expanded inside it:
1 \verbtocs{\Ob}|{|
2 \verbtocs{\Cb}|}|
3 \newcommand\bracearg[1]{%
4 \def\text{#1}%
{xstring}
5 \scancs{\result}{\Ob\text\Cb}%
{\a }
6 \result}
7
8 \bracearg{xstring}\par
9 \bracearg{\a}
16 It
is possible to make much more simple using \detokenize. The macro becomes:
\newcommand\bracearg[1]{\detokenize{{#1}}}
19
1 \noexploregroups
2 \StrRemoveBraces{a{b{c}d}e{f}g}[\mycs]
3 \meaning\mycs
macro:->ab{c}defg
4
macro:->abcdefg
5 \exploregroups
6 \StrRemoveBraces{a{b{c}d}e{f}g}[\mycs]
7 \meaning\mycs
4.8 Examples
Here are some very simple examples involving the macros of this package in programming purposes.
4.8.1 Example 1
We want to substitute the 2 first \textit by \textbf in the control sequence \myCS which contains
\textit{A}\textit{B}\textit{C}
We expect: ABC
1 \expandarg
2 \def\myCS{\textit{A}\textit{B}\textit{C}}
3 \def\pattern{\textit} ABC
4 \def\replace{\textbf}
5 \StrSubstitute[2]{\myCS}{\pattern}{\replace}
It is possible to avoid to define \pattern and \replace: a ”snare” can be used. It can be a control sequence which
expansion is empty, like the famous \empty. The code would have been:
\StrSubstitute[2]{\myCS}{\empty\textit}{\empty\textbf}
With this code, in both arguments, the first token \empty is expanded to ”nothing” and the following significant tokens
\textit and textbf are left unchanged.
By this way, \empty is a way to ”hack” \expandarg: it allows to avoid the expansion of all the other tokens. The control
sequence \noexpand can be used instead of \empty for the same result.
4.8.2 Exemple 2
Here, we try to write a macro which gobbles n syntax units in a string from a given position, and assigns the result to a
control sequence.
Let’s call this macro StringDel and let’s give it this syntax:
\StringDel{string}{position}{n}{\name_of_result}
We can proceed like this: take the string before the position and save it. Then remove n + position syntax units from
the initial string, and add (concatenate) this result to the string previously saved. This gives the following code:
1 \newcommand\StringDel[4]{%
2 \begingroup
3 \expandarg% locally in this group
4 \StrLeft{\empty#1}{\number\numexpr#2-1}[#4]%
5 \StrGobbleLeft{\empty#1}{\numexpr#2+#3-1}[\StrA]%
6 \expandafter\expandafter\expandafter\endgroup
7 \expandafter\expandafter\expandafter\def
8 \expandafter\expandafter\expandafter#4%
9 \expandafter\expandafter\expandafter macro:->aefgh
10 {\expandafter#4\StrA}% macro:->a\textbf 3d
11 }
12
13 \noexploregroups
14 \StringDel{abcdefgh}{2}{3}{\cmd}
15 \meaning\cmd
16
17 \StringDel{a\textbf{1}b\textbf{2c}3d}{3}{4}{\cmd}
18 \meaning\cmd
20
To concatenate, the LATEX macro \g@addto@macro could have been used, leading to a lighter code without the huge bridge
of \expandafter. The assignment17 can be written like this:
\expandafter\g@addto@macro\expandafter#4\expandafter{\StrA}\endgroup
4.8.3 Example 3
Let’s try to write a macro \tofrac that transforms an argument of this type ”a/b” into ” ab ”.
First of all, let’s cancel the expansion of arguments with \noexpandarg, we do not need expansion here. Then, it’s easy
to cut what is before and behind the first occurrence of ”/” (assumed there is a single occurrence) and assign it to \num
and \den and simply call the macro \frac :
1 \noexpandarg
2 \newcommand\tofrac[1]{%
3 \StrBefore{#1}{/}[\num]%
4 \StrBehind{#1}{/}[\den]%
√
5 $\frac{\num}{\den}$% 15 un+1 am √x+ x
9 un an
6 } x2 +x+1
7 \tofrac{15/9}
8 \tofrac{u_{n+1}/u_n}
9 \tofrac{a^m/a^n}
10 \tofrac{x+\sqrt{x}/\sqrt{x^2+x+1}}
4.8.4 Example 4
Let’s try to write a macro \boldafter which writes in bold the first word that follows the word contained in the expansion
of \word.
1 \newcommand\boldafter[2]{%
2 \noexpandarg
3 \StrBehind[1]{#1 }{ #2 }[\word]%
4 \expandarg
5 \StrBefore{\word}{ }[\word]%
6 \StrSubstitute[1]{#1}{\word}{\textbf{\word}}% The xstring package is new
7 } The xstring package is new
8
The xstring package is new
9 \boldafter{The xstring package is new}{xstring}
10
4.8.5 Example 5
How to reverse the order of the 2 first control sequences? For this, a macro \swaptwofirst does the job and displays
the result. But this time, it is not possible to seek the token \ (catcode 0) with the macros of xstring. This is why the use
of \scancs is necessary: after the detokenization of the argument, it becomes possible to search the char \ (catcode 12).
At line 5, a retokenization is done by \tokenize and \before and \after are swapped at this moment.
17 The macro \g@addto@macro can be used if the catcode of ”@” is temporarily changed with \makeatletter and restored with \makeatother
21
1 \verbtocs{\antislash}|\|
2 \newcommand\swaptwofirst[1]{%
3 \begingroup
4 \fullexpandarg
5 \scancs[0]\mystring{#1}%
6 \StrBefore[3]{\mystring}{\antislash}[\firsttwo]%
7 \StrBehind{\mystring}{\firsttwo}[\others]
8 \StrBefore[2]{\firsttwo}{\antislash}[\before]
BAC
9
10
\StrBehind{\firsttwo}{\before}[\after]%
\tokenize\myCS{\after\before\others}%
AB123
11 \myCS
12 \endgroup
13 }
14
15 \swaptwofirst{\underline{A}\textbf{B}\textit{C}}
16
17 \swaptwofirst{\Large\underline{A}\textbf{B}123}
4.8.6 Example 6
In a string, we want to find the nth word between 2 given delimiters. For this, let’s write a macro \findword with
an optional argument which content is the delimiter (space by default), 1 argument containing the string and an other
argument containing the number n.
The macro \findword artfully uses \StrBetween and \numexpr:
1 \newcommand\findword[3][ ]{%
2 \StrBetween[#3,\numexpr#3+1]{#1#2#1}{#1}{#1}%
3 }
|de f|
4 \noexpandarg
|2 3 |
5 |\findword{a bc d\textbf{e f} gh}{3}|
6
⋆
⋆ ⋆
22