SAS中是否有子字函数?

SAS中是否有子字函数?,sas,Sas,我知道SAS中有一个子字符串函数,但是有没有一个函数可以从字符串返回前n个单词?我不知道有哪一个函数可以做到这一点。您可以使用scott提供的函数组合,也可以使用正则表达式兔子洞进行类似操作,其中大括号中的数字是所需的字数: substring = prxchange('s/((\w+ ){2}).*/\1/',-1,original_string); 这假设您的单词由字母数字字符组成,并且它们之间用空格分隔。(可能还有很多其他特殊情况也会破坏它。)我不知道有哪一个函数能做到这一点。您可以使用

我知道SAS中有一个子字符串函数,但是有没有一个函数可以从字符串返回前n个单词?

我不知道有哪一个函数可以做到这一点。您可以使用scott提供的函数组合,也可以使用正则表达式兔子洞进行类似操作,其中大括号中的数字是所需的字数:

substring = prxchange('s/((\w+ ){2}).*/\1/',-1,original_string);

这假设您的单词由字母数字字符组成,并且它们之间用空格分隔。(可能还有很多其他特殊情况也会破坏它。)

我不知道有哪一个函数能做到这一点。您可以使用scott提供的函数组合,也可以使用正则表达式兔子洞进行类似操作,其中大括号中的数字是所需的字数:

substring = prxchange('s/((\w+ ){2}).*/\1/',-1,original_string);

这假设您的单词由字母数字字符组成,并且它们之间用空格分隔。(可能还有很多其他特殊情况也会破坏它。)

没有直接的子词函数。但是,您可以使用呼叫扫描来查找单词所在的位置

%let words=4;
data _null_;
infile datalines truncover;
input @1 text $500.;
position=0;
length=0;
do _t = 1 to &words;
call scan(text,_t,position,length);
end;
newvar = substr(text,1,position+length);
put _all_;
datalines;
The rain in Spain falls mainly in the plains
Spruce Goose is on the loose
The quick brown fox jumps over the lazy dog
;;;;
run;

注释中建议的直接解决方案(围绕函数扫描调用循环)更易于编写,而这避免了在将单词重新组合在一起时调用CATX(或类似),因此在某些情况下可能执行得更快。

没有直接的子单词函数。但是,您可以使用呼叫扫描来查找单词所在的位置

%let words=4;
data _null_;
infile datalines truncover;
input @1 text $500.;
position=0;
length=0;
do _t = 1 to &words;
call scan(text,_t,position,length);
end;
newvar = substr(text,1,position+length);
put _all_;
datalines;
The rain in Spain falls mainly in the plains
Spruce Goose is on the loose
The quick brown fox jumps over the lazy dog
;;;;
run;

注释中建议的直接解决方案(围绕函数扫描调用循环)更易于编写,同时避免了在将单词重新组合到一起时调用CATX(或类似),因此在某些情况下可能会执行得更快。

对于SAS 9.2及更高版本,您可以使用PROC FCMP运行自己的函数。这将允许您封装循环,并将其他人提到的内容扫描到可在任何数据步骤中重用的表单中

options cmplib=work.fns;

proc fcmp outlib=work.fns.fns;
function nwords(str $, n) $;
    nstr = countw(str);
    if nstr <= n then do;
        return (str);
    end;
    else do;
        attrib outStr length=$200;
        outStr = "";
        do i=1 to n;
            outStr = strip(outStr) || " " || scan(str,i);
        end;
        return (outStr);
    end;
endsub;
run;
quit;

data test;
str = "I went to the store to get milk and bread.";
format substrs $200.;
do i=1 to 5;
    substrs = nwords(str,i);
    output;
end;
run;
options cmplib=work.fns;
proc fcmp outlib=work.fns.fns;
函数nwords(str$,n)$;
nstr=countw(str);

如果使用SAS 9.2及更高版本的nstr,则可以使用PROC FCMP滚动您自己的函数。这将允许您封装循环,并将其他人提到的内容扫描到可在任何数据步骤中重用的表单中

options cmplib=work.fns;

proc fcmp outlib=work.fns.fns;
function nwords(str $, n) $;
    nstr = countw(str);
    if nstr <= n then do;
        return (str);
    end;
    else do;
        attrib outStr length=$200;
        outStr = "";
        do i=1 to n;
            outStr = strip(outStr) || " " || scan(str,i);
        end;
        return (outStr);
    end;
endsub;
run;
quit;

data test;
str = "I went to the store to get milk and bread.";
format substrs $200.;
do i=1 to 5;
    substrs = nwords(str,i);
    output;
end;
run;
options cmplib=work.fns;
proc fcmp outlib=work.fns.fns;
函数nwords(str$,n)$;
nstr=countw(str);

如果nstr这看起来像是一个黑客,所以我不会发布作为答案,但这应该可以工作
first3=catx(扫描(字符串,1),“”,扫描(字符串,2),“”,扫描(字符串,3))这似乎是一个黑客行为,所以我不会发布作为答案,但这应该可以工作
first3=catx(扫描(字符串,1),“”,扫描(字符串,2),“”,扫描(字符串,3))
我考虑过回答这个问题,但我要提醒大家,
PROC FCMP
不是很有效,特别是在这样的情况下-它比相同的数据步骤代码慢或相同(最多),并且在某些情况下慢得多,由于SAS能够使用数据步代码实现某些快捷方式,而FCMP函数无法实现这些快捷方式。@Joe,我同意。除非你处理的是一个超大的数据集,或者是一些第二个问题的分数,否则这应该是可以的。否则我会在宏中滚动这个。我考虑过回答这个问题,但我要提醒大家,
PROC FCMP
不是很有效,特别是在这样的情况下-它比相同的datastep代码慢或相同(最多),在某些情况下慢得多,由于SAS能够使用数据步代码实现某些快捷方式,而FCMP函数无法实现这些快捷方式。@Joe,我同意。除非你处理的是一个超大的数据集,或者是一些第二个问题的分数,否则这应该是可以的。否则我会在宏中滚动这个。