Falsche Fehler-Meldung bei K-Funktion Invalid third argument to function KSUBSTRB

Hallo,
beim Einlesen von Fremd-Daten muß ich mit substr() arbeiten. Da unser Base-Code seit ca. März 2009 unicodefähig ist verwende ich natürlich ksubstr().
Soweit so gut.
Leider arbeitet ksubstrB() nicht wie erwartet! Siehe Code:

data aaa;
length _nPOSNETTOWERT $44.;
_nPOSNETTOWERT="15,95"; output;
_nPOSNETTOWERT="39,5"; output;
_nPOSNETTOWERT="18,35"; output;
_nPOSNETTOWERT="4,97491638795986622073578595317725752508"; output;
_nPOSNETTOWERT="0"; output;
_nPOSNETTOWERT="19"; output;
_nPOSNETTOWERT="44,95"; output;
_nPOSNETTOWERT="12,5630252100840336134453781512605042017"; output;
run;
data bbb;
set aaa;
xxx=_nPOSNETTOWERT;
xxx2=_nPOSNETTOWERT;
if kindexc(xxx,',') then do;
xxx=ktrim(kscan(_nPOSNETTOWERT,1,','))||','||ksubstrB(kscan(_nPOSNETTOWERT,2,','),1,10);
end;
nPOSNETTOWERT=input(xxx, numx10.);
put xxx= _nPOSNETTOWERT= nPOSNETTOWERT=;
run;

Und der (gekürzte) LOG dazu:

1821 data bbb;
1822 set aaa;
1823 xxx=_nPOSNETTOWERT;
1824 xxx2=_nPOSNETTOWERT;
1825 if kindexc(xxx,',') then do;
1826 xxx=ktrim(kscan(_nPOSNETTOWERT,1,','))||','||ksubstrB(kscan(_nPOSNETTOWERT,2,','),1,10);
1827 end;
1828 nPOSNETTOWERT=input(xxx, numx10.);
1829 put xxx= _nPOSNETTOWERT= nPOSNETTOWERT=;
1830 run;

NOTE: Invalid third argument to function KSUBSTRB.
xxx=15,95 _nPOSNETTOWERT=15,95 nPOSNETTOWERT=15.95
NOTE: Invalid third argument to function KSUBSTRB.
xxx=39,5 _nPOSNETTOWERT=39,5 nPOSNETTOWERT=39.5
NOTE: Invalid third argument to function KSUBSTRB.
xxx=18,35 _nPOSNETTOWERT=18,35 nPOSNETTOWERT=18.35
xxx=4,9749163879 _nPOSNETTOWERT=4,97491638795986622073578595317725752508 nPOSNETTOWERT=4.97491638
xxx=0 _nPOSNETTOWERT=0 nPOSNETTOWERT=0
xxx=19 _nPOSNETTOWERT=19 nPOSNETTOWERT=19
NOTE: Invalid third argument to function KSUBSTRB.
xxx=44,95 _nPOSNETTOWERT=44,95 nPOSNETTOWERT=44.95
xxx=12,5630252100 _nPOSNETTOWERT=12,5630252100840336134453781512605042017 nPOSNETTOWERT=12.5630252
NOTE: There were 8 observations read from the data set WORK.AAA.
NOTE: The data set WORK.BBB has 8 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.05 seconds
cpu time 0.01 seconds

Den Work-Around dazu habe ich auch schon, das ist also nicht das Problem, mich erschreckt die Qualität der Unicode-Unterstützung von SAS-92!
Der Work-Around (ohne LOG, ist nicht nötig, da fehlerfrei):

data bbb; /* Work-Around, Variante 1 (scan statt kscan, fehlerfrei) */
set aaa;
xxx=_nPOSNETTOWERT;
xxx2=_nPOSNETTOWERT;
if kindexc(xxx,',') then do;
xxx=ktrim(kscan(_nPOSNETTOWERT,1,','))||','||ksubstrB(scan(_nPOSNETTOWERT,2,','),1,10);
end;
nPOSNETTOWERT=input(xxx, numx10.);
put xxx= _nPOSNETTOWERT= nPOSNETTOWERT=;
run;
data bbb; /* Work-Around, Variante 2 (kscan() ausgelagert, fehlerfrei) */
set aaa;
xxx=_nPOSNETTOWERT;
xxx2=_nPOSNETTOWERT;
if kindexc(xxx,',') then do;
xxx2=kscan(_nPOSNETTOWERT,2,',');
xxx=ktrim(kscan(_nPOSNETTOWERT,1,','))||','||ksubstrB(xxx2,1,10);
end;
nPOSNETTOWERT=input(xxx, numx10.);
put xxx= _nPOSNETTOWERT= nPOSNETTOWERT=;
run;

Wie gesagt, der Work-Around ist gefunden, also kein Problem. Mich erschreckt die Qualität der Unicode-Unterstützung von SAS-92!
Wie sieht es bei anderen Anwendern mit Unicode aus? Haben andere Anwender bessere oder ähnliche Erfahrungen gemacht?

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)

Hilfe für meinen Kollegen

Hans, hier ein leerer Kommentar zu Deinem Beitrag.
Jetzt kannst/darst Du weiter berichten ;-)

Gruß, Andrea

Meldung doch berechtigt, aber ...

Hallo,
das Unicode-Thema bzw. die DBCS-Unterstützung durch SAS-92 ist ein undankbares Thema.

  1. Beruht mein obiger Beitrag auf einem Denkfehler!
    Ich glaubte substrN() und ksubstrB() würden zusammengehören, wie z.B. kupcase() der DBCS counterpart zu upcase() ist.
    Leider ist das nicht so, also ist die Fehler-/Note-Meldung berechtigt.
  2. Hat SAS aufgrund des von mir gemeldeten Problems einen Fehler in der kscan()-Funktion gefunden und die Reparatur für SAS-93 zugesagt. Netter Nebeneffekt :-))
    Die Funktion kscan() ist der DBCS counterpart zu scan().
  3. Fehlt zur DBCS-Unterstützung der DBCS counterpart zu substrN()!
    Der Haupt-Unterschied zw. substr() und substrN() ist für mich, dass man bei substrN "über das Ende" vom "string" hinauslesen kann: If the length that you specify extends beyond the end of the string, the result is truncated at the end, so that the last character of the result is the last character of the string.
    Genau diese Funktionalität hatte ich gesucht, und geglaubt sie bei ksubstrB gefunden zu haben. Dass das ein Denk-Fehler war ist mittlerweile klar.

Dass der Workaround aus meinem Start-Beitrag geklappt hat war scheinbar Zufall. Hier der korrekte Workaround:

data bbb;
set aaa;
xxx=_nPOSNETTOWERT; /* Zahl mit zu vielen Nachkommastellen */
if kindexc(xxx,',') then do;
xxx=ktrim(kscan(_nPOSNETTOWERT,1,',')) /* Zahl mit max. 10 Nachkommastellen */
||','
||ksubstr(kscan(_nPOSNETTOWERT,2,',')
,1
,min(10,length(kscan(_nPOSNETTOWERT,2,',')))
);
end;
nPOSNETTOWERT=input(xxx, numx10.);
put xxx= _nPOSNETTOWERT= nPOSNETTOWERT= ;
run;

Gruß
Hans Kneilmann, Schäfer Shop GmbH (SSI)