RPM Expression
RPM expressions is a "sublanguage" in RPM. From the RPM manual (opens in a new tab),
Expression expansion can be performed using
%[expression]
. An expression consists of terms that can be combined using operators. Rpm supports three kinds of terms, numbers made up from digits, strings enclosed in double quotes (eg"somestring"
) and versions enclosed in double quotes preceded by v (egv"3:1.2-1"
). Rpm will expand macros when evaluating terms.You can use the standard operators to combine terms: logical operators
&&
,||
,!
, relational operators!=
,==
,<
,>
,<=
,>=
, arithmetic operators+
,-
,/
,*
, the ternary operator? :
, and parentheses. For example,%[ 3 + 4 * (1 + %two) ]
will expand to "15" if%two
expands to "2". Version terms are compared using rpm version ([epoch:]version[-release]) comparison algorithm, rather than regular string comparison.Note that the
%[expression]
expansion is different to the%{expr:expression}
macro. With the latter, the macros in the expression are expanded first and then the expression is evaluated (without re-expanding the terms). Thusrpm --define 'foo 1 + 2' --eval '%{expr:%foo}'
will print "3". Using
%[%foo]
instead will result in the error that "1 + 2" is not a number.Doing the macro expansion when evaluating the terms has two advantages. First, it allows rpm to do correct short-circuit processing when evaluation logical operators. Second, the expansion result does not influence the expression parsing, e.g.
%["%file"]
will even work if the%file
macro expands to a string that contains a double quote.
This section digs into more of the advanced and technical details.
First, a (way simpler) Rust declarative implementation is available
in rpmspec-rs
(opens in a new tab).
The following section uses the following symbols:
- 🟰: 2 inputs must be of the same type.
- 🟩: not fallible (i.e. never produces an error), given 🟰 is satisfied.
Second, there are 4 unary, 10 binary, and 1 tertiary operators:
-a
: negate a numerical value.- Err when used on non-numerical values.
!a
: negate the value, return either 1 or 0. 🟩- Non-zero numbers when negated produce
0
. - Non-empty texts/strings when negated produce
0
. - Other values (including versions) produce
1
.
- Non-zero numbers when negated produce
a && b
: the "and" operator. 🟰🟩- Num:
0
unless both values are non-zero. - Text:
0
unless both values are not empty. - Ver: always produce
a
.
- Num:
a || b
: the "or" operator. 🟰🟩- Num:
1
unless both values are zero. - Text:
1
unless both values are empty. - Ver: always produce
b
.
- Num:
a != b
🟰🟩a == b
🟰🟩a < b
🟰🟩a > b
🟰🟩a <= b
🟰🟩a >= b
🟰🟩a + b
🟰- Num: Addition of 2 numbers
- Text: Joining 2 texts together (without spaces in the middle)
- Ver: Err
a - b
🟰- The same as
a + (-b)
- The same as
a / b
🟰- Num: if
b != 0
, performs division. - Otherwise err.
- Num: if
a * b
- Num: performs multiplication.
- Otherwise err.
a ? b : c
🟩b
,c
🟰- If
!!a
produces1
, evaluate tob
. - Otherwise, evaluate to
c
.