Das hier gerade auch noch:
#$var_\d{1,3}(_\d)?#
Ich versuches mal in meinem laienhaften regex Verständnis zu erklären.\d{1,3} = Zahlen, mindestens 1, maximal 3
Ja, \d ist gleichbedeutend zu [0-9]
(_\d)? bedeutet wegen dem Fragezeichen "einmal oder keinmal" und \d reicht auch weil ja immer nur eine Zahl. Man braucht also gar keine "Oder" Verknüpfung?
\d alleine reicht nicht, du willst da $var_123__1 oder $var_123__2 finden - wenn du \d alleine notierst und den _ vorher schon dranpackst, würdest du auch $var_123_ finden, nicht nur $var_123.
Eure restlichen Ergüsse wie
"Allenfalls brauchst du negative lookaheadsm was das Ganze aber komplexer macht."
Ignorieren, braucht man sehr selten und sind wirklich sehr komplex und schwierig zu verstehen.
"Ja, non-capturing parenthesis machen auch gebrauch von Klammer und Fragezeichen ;)"
gewöhnlich: #$var_\d{1,3}(_\d)?#
mit non-capturing parenthesis: #$var_\d{1,3}(?:_\d)?#
Wenn du dir das Array (bzw. beide) ansiehst, welches von preg_match_all produziert wird, wirst du den Unterschied schnell verstehen.
In deinem Fall ist es imho egal ob du ?: zusätzlich notierst oder nicht da du das Subpattern nur als Mittel zum Zweck verwendest im das _\d gemeinsam als optional zu kennzeichnen.