This page is a lookup for the RPGLE string built-in functions: what each one takes, what it returns, and the edge cases that cause run-time errors or surprising results. For worked patterns such as parsing, building messages and CCSID handling, read ILE RPG String Handling. The complete list of BIFs is in the RPGLE Built-in Functions Reference.
All examples are free-form RPGLE. Positions in a string start at 1.
String BIFs at a glance
| BIF | What it does | Returns |
|---|---|---|
%subst | Part of a string | A string of the same kind as the source |
%scan | Position of one string inside another | Integer; 0 when not found |
%scanrpl | Replace every occurrence of one string with another | A string |
%trim, %triml, %trimr | Remove blanks or listed characters | A varying-length string |
%replace | Replace part of a string, or insert | A string |
%len | Length of a value | Integer |
%char | Convert a number, date, time, timestamp or other string to text | A character string |
%check, %checkr | First character not on an allowed list | Integer; 0 when all are allowed |
%xlate | Translate characters one-for-one | A string |
%SUBST
Returns part of a string. The left-side assignment form and the range rules have their own page, the RPGLE %SUBST Reference.
%subst(string : start {: length})
| Parameter | Meaning |
|---|---|
string | The source value |
start | First position to return, starting at 1 |
length | Number of characters to return. If omitted, the result runs to the end of the string |
dcl-s name char(20) inz(' Smith, Anna');
dcl-s surname varchar(20);
surname = %subst(%trim(name) : 1 : 5); // 'Smith'
%SCAN
Returns the position of the first occurrence of one string inside another, or 0 when it is not found. To find every match, or to replace every occurrence with %scanrpl, see the RPGLE %SCAN and %SCANRPL Reference.
%scan(search : source {: start {: length}})
The search argument comes first and the string being searched second. This is the reverse of the order many other languages use. The optional start is the first position to search from, and the optional length limits how many characters are searched. The search is case-sensitive.
dcl-s pos int(10);
pos = %scan(',' : 'Smith, Anna'); // 6
pos = %scan('x' : 'abc'); // 0
pos = %scan('a' : 'banana' : 3); // 4, searching from position 3
%TRIM, %TRIML and %TRIMR
%trim removes blanks from both ends of a string. %triml removes leading blanks only, and %trimr removes trailing blanks only.
%trim(string {: characters})
With the optional second parameter, the function removes the characters you list instead of blanks.
dcl-s cleaned varchar(20);
cleaned = %trim(' ABC '); // 'ABC'
cleaned = %trim('**ABC**' : '*'); // 'ABC'
The function returns a new value. It does not change the variable you pass.
%REPLACE
Replaces part of a string, or inserts text.
%replace(replacement : source {: start {: length}})
| Parameter | Meaning |
|---|---|
replacement | The text to put in |
source | The string to change |
start | Where to begin. Defaults to 1 |
length | How many characters of source to replace. Defaults to the length of replacement |
dcl-s result varchar(20);
result = %replace('XX' : 'ABCDEF' : 3 : 2); // 'ABXXEF'
result = %replace('-' : 'ABCDEF' : 3 : 0); // 'AB-CDEF', length 0 inserts
%replace is the BIF to use for an insert. To add text at the end, give start as one more than the length of the source.
%LEN
Returns the length of a value.
%len(expression)
For a varying-length field, %len is the current length, and %len(field : *max) is its declared maximum. For a fixed-length field, it is the declared length, whatever the field holds. For alphanumeric data the length is in bytes.
dcl-s fixedTxt char(10) inz('Hi');
dcl-s varTxt varchar(10) inz('Hi');
// %len(fixedTxt) is 10
// %len(varTxt) is 2
// %len(%trim(fixedTxt)) is 2
%CHAR
Converts a value to character data.
%char(expression {: format | ccsid})
A number converts to character data without leading zeros, with a minus sign when it is negative. The decimal positions of the field are kept. For a date, time or timestamp, the second parameter is a format. For character, graphic or UCS-2 data, the second parameter is a CCSID.
dcl-s text varchar(30);
dcl-s count int(10) inz(42);
text = 'Orders: ' + %char(count); // 'Orders: 42'
For a date, time or timestamp, the second parameter chooses the output format. Without it, the result uses the format the field was declared with.
dcl-s due date(*iso) inz(d'2026-10-05');
dcl-s shown varchar(10);
shown = %char(due : *usa); // '10/05/2026'
%CHECK and %CHECKR
Return the position of the first character in a string that is not in a list of allowed characters, or 0 when every character is allowed. %check scans from the left. %checkr scans from the right.
%check(comparator : base {: start})
dcl-s bad int(10);
bad = %check('0123456789' : '12a4'); // 3, the 'a'
bad = %check('0123456789' : '1234'); // 0, all digits
%XLATE
Translates characters in a string, using one list of characters to find and a parallel list to substitute.
%xlate(from : to : string {: start})
dcl-s result varchar(20);
result = %xlate('abc' : 'ABC' : 'a cat'); // 'A CAt'
Each character found in the from list is replaced by the character in the same position in the to list. Characters not in the from list are left alone.
Multibyte data
In the IBM i 7.5 reference, %subst, %scan, %replace, %check and %xlate also accept a final optional parameter, *natural or *stdcharsize. It chooses whether positions and lengths count characters or bytes, and it only matters for multibyte data such as UTF-8. The examples on this page use single-byte data and do not need it. For CCSID handling, read the ILE RPG String Handling tutorial.
Opcode to BIF mapping
Older fixed-format code uses opcodes for the same jobs. They still compile; use the BIF in new code. The full list is in the RPGLE Opcode Reference.
| Fixed-format opcode | Free-form equivalent |
|---|---|
SUBST | %subst |
SCAN | %scan |
CAT | the + operator, usually with %trim |
CHECK | %check |
XLATE | %xlate |
Common mistakes
- Swapping the arguments of
%scan. The thing you look for is the first argument. - Using the result of
%scanwithout testing for 0. - Concatenating a fixed-length field without
%trim, which leaves its padding blanks in the result. - Expecting
%trimto change the variable. Assign the result to a variable. - Passing a
startandlengthto%substthat run past the end of the string. - Calling
%substwith astartorlengthbeyond the current length, for example on the result of%trimof a field that may be blank. Test%lenfirst.
FAQ
Why does %SCAN return 0?
The search string was not found, or the start position is past the last possible match. Zero is the normal “not found” result and is not an error.
Does %TRIM change the original field?
No. It returns a new value. Assign it to a variable to keep it.
What is the difference between %SUBST and %REPLACE?
%subst reads part of a string. %replace returns a new string with part of the source replaced or with text inserted.
Related BIFs
- RPGLE Built-in Functions Reference: the full index by task.
- RPGLE Numeric and Conversion BIFs Reference:
%int,%dec,%editcand the rounding rules, for when a string must become a number. - RPGLE Date and Time BIFs Reference:
%date,%diffand%subdt.
Summary
- Read the teaching version, ILE RPG String Handling, for parsing patterns and CCSID handling.
- Check how lengths and types behave in RPGLE Data Types, Lengths and Precision.
- Return to the RPGLE Built-in Functions Reference to find the other BIF families.
Test
ok