Ich würde das mit einer `clist` machen. Testet auch auf Leerzeichen und nutzt das `l3msg`-Interface für Warnungen.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \l_allowed_chars_clist
\clist_set:Nn \l_allowed_chars_clist { 0, 1, a, b }
\msg_new:nnn { noname } { erroneous-input } { Erroneous~character~`#1' }
\cs_new_protected:Npn \test_mit_tl:n #1
{
% Check for spaces
\seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 }
\int_compare:nT { \seq_count:N \l_tmpa_seq > 1 }
{ \msg_warning:nnn { noname } { erroneous-input } { ~ } }
% Check for invalid tokens
\seq_set_split:Nnn \l_tmpa_seq { } { #1 }
\tl_map_inline:nn { #1 }
{
\clist_if_in:NnF \l_allowed_chars_clist { ##1 }
{ \msg_warning:nnn { noname } { erroneous-input } { ##1 } }
}
}
\NewDocumentCommand \Befehl {m}
{
\test_mit_tl:n {#1}
}
\ExplSyntaxOff
\begin{document}
\Befehl{12 ab}
\end{document}