Hallo zusammen,
ich sitze schon gefühlt schon seit Ewigkeiten vor folgendem Problem. Natürlich habe ich versucht mich zu belesen und herauszufinden wie ich es löse, jedoch vergebens 😞
Wie kann ich folgendes innerhalb einer Zelle gut leserlich trennen:
- Wörter die durch Sonderzeichen verbunden sind, z.B.: Brief/Post oder ERF!RSA oder SOMMER:WINTER
- Wörter die hintereinander ohne Leerzeichen geschrieben sind aber immer mit Großbuchstaben beginnen, z.B. PostWichtige
- Zahl und Buchstabe trennen (zuerst kommt die Zahl, dann das Wort, z.B. 225,00Freitext oder 15.01.2021Freitext oder 2RSA:
Es wäre mir eine große Hilfe wenn mir jemand helfen könnte. Wenn es einen data step gibt, der keine Makros verwendet, noch besser :).
Viele Grüße
Katrin
Hi @Katrin1606 ,
habe mal eine Lösung auf der Basis von RegEx und den SAS-Funktionen scan & count entwickelt. Für die erste beiden Fälle habe ich Lösungen entwickelt die mit beliebig vielen verbundenen "Wörtern" umgehen kann. Für den letzten Fall habe ich bisher noch keine Lösung die mit n Wörtern umgehen kann - solltest du das benötigen sag Bescheid. Zu RegEx in SAS empfehle ich immer das Cheat-Sheet. Der Code ist nicht wirklich kommentiert, ich hoffe er spricht für sich.
data work.aaa(drop=p1 p2 p3 c1 c2 i j l);
length w1 w2 w3 $256.;
* Sonderzeichen;
str2 = "ERF!RSA";
p2 = prxparse('/\W/');
c2 = countw(str2, '', 'P') ;
do j = 1 to c2;
w2 = scan(str2, j, '', 'P');
output;
end;
* camelCase-Worttrennung;
str1 = "PostWichtigeTest";
p1 = prxparse('/[A-Z]/');
c1 = countw(str1, "", 'U');
*w1 = substr(str1, 1, prxmatch(p1, substr(str1, 2)));
do i = 1 to c1;
if i = 1 then l = 1;
w1 = substr(str1, l, prxmatch(p1, substr(str1, l + 1)));
l = l + length(w1);
output;
end;
* Zahlen-Worttrennung;
str3 = "225,00Freitext";
p3 = prxparse('/\d[A-Z]/');
w3 = substr(str3, 1, prxmatch(p3, str3));
output;
w3 = substr(str3, prxmatch(p3, str3) + 1);
output;
run;
Viele Grüße
David
Hallo Katrin,
ich denke auch, dass man hier mit regulären Ausdrücken arbeiten sollte. Wenn es das Ziel ist, den vorhandenen Text in einer Character-Variablen geeignet abzuändern, kann man dies direkt mit der PRXCHANGE-Funktion tun.
Beispiel:
/* Erzeugen von Beispieldaten */
data have;
input c $50.;
cards;
z.B. ein Brief/Post von heute/gestern
ERF!RSA
Katalog SOMMER:WINTER 2021
PostWichtige
EUR225,00Freitext
ab15.01.2021Freitext
100 kW
2RSA
c/o
30/100
Neu/Änderungen
TabelleÜbersicht
Schließung/Öffnung
Spaß+Ärger
;
/* Anwenden von vier Änderungsregeln */
data want;
set have;
c=prxchange('s/([[:alpha:]]{2})([[:punct:]])([[:alpha:]]{2})/$1 $2 $3/',-1,c);
c=prxchange('s/([a-zäöüß]{2})([A-ZÄÖÜ])/$1 $2/',-1,c);
c=prxchange('s/(\d)([[:alpha:]])/$1 $2/',-1,c);
c=prxchange('s/([[:alpha:]])(\d)/$1 $2/',-1,c);
run;
Die "vier Änderungsregeln" bedeuten:
Die Regeln werden jeweils "so oft wie möglich" (zweites Argument -1) angewandt.
Wenn noch Verfeinerungen oder Ergänzungen der Regeln nötig werden, kann man die regulären Ausdrücke sicherlich nachjustieren oder weitere hinzufügen.
REGex ist sicherlich sehr mächtig, abder ich bevorzüge die bewährte Functionen weil das Lesen für mich einfacher ist.
Was nicht für mich klar ist, aber ich have die trennende Sonderzeichen beibehalten. Und kann auch Komma und Punkt als Trennzeichen vorkommen (Also, nicht nur in Zahlen).
data test; input have $char30.; length = length(have); /* Position Zahl vorne - Finde erste Zeichen, kein Zahl und auch nicht , oder .*/ split_pos_zahl=findc(have,'.,','DK'); /* Position Sonderzeichen Finde erste nicht-alphabetisch Zeichen */ split_pos_sonder = findc(have,'ÄÖÜäöüß','AK'); /* Gross/klein : Erste Grosszeichen, ignoriere 1. */ split_pos_gross = findc(have,'ÄEÖÜ','U',2); if 1 < split_pos_zahl < length then best_pos = split_pos_zahl; else if 1 < split_pos_sonder < length then best_pos = split_pos_sonder; else if 1 < split_pos_gross < length then best_pos = split_pos_gross; if Best_pos > 1 then want = substrn(have,1,best_pos-1)||' '||substrn(have,best_pos); cards; Brief/Post ERF!RSA SOMMER:Winter PostWichtige 225,00Freitext 15.01.2021Freitext 2RSA: ; run;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!