如何在SAS中扫描字符串并动态转换
How to scan the string and convert dynamically in SAS
假设我有两个字符串要从 SAS 程序名称转换为 table 数字。
我的目标是将第一个 "f-2-2-7-5-vcb" 转换为“2.2.7.5”。
这应该动态完成。喜欢 "f-2-2-12-1-2-hbd87q",
它需要是“2.2.12.1.2”。
如何实现?
data input;
input str $ 1-20;
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
;
run;
data want;
set input;
Sub=compress(substr(str,3,length(str)),,'kd') ;
run;
有点长,但这对我来说很好。
- 使用 FIND() 查找第一个 '-'
- 使用 REVERSE() 和 FIND() 查找
最后一个 '-'
- 使用 SUBSTR() 和 metrics + math 从上面删除第一个和
最后一个组件
使用 TRANSLATE() 将 - 转换为句点。
z=find(str, '-');
end=find(strip(reverse(str)), '-');
string = translate(substr(str, z+1, length(str) - z - end), ".", "-");
正则表达式只能匹配破折号分隔的数字序列。提取的匹配项可以使用 translate
.
进行转换
data input;
input str $ 1-20;
rx = prxparse ("/^.*?((\d+)(-\d+)*)/");
if prxmatch(rx,str) then do;
call prxposn (rx,1,s,e);
name = substr(str,s,e);
name = translate(name,'.','-');
end;
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
funky2-2-1funky
f-2-hb17
a2bfunky
;
run;
如果只有数字的令牌序列前面是一个以数字结尾的令牌,或者后面是一个以数字开头的令牌,则会出现一种奇怪的情况。
data input;
input str $ 1-20;
string=translate(prxchange('s/\w+?\-(.*)\-\w+//',-1,strip(str)),'.','-');
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
;
run;
您可以在一行中完成此操作。使用 subtr 将文本保留在第二个词和最后一个词之间:
翻译(substr(str,find(str,scan(str,2,'-')),find(str,scan(str,-1,'-'))-find (str,scan(str,2,'-'))-1),'.','-')
- find(str,scan(str,2,'-') : 找到第二个的起始位置
单词。
- find(str,scan(str,-1,'-') : 找到最后一个的起始位置
单词。
- step2 - find(str,scan(str,2,'-'))-1 : 找到第二个的结束位置
最后一个字(要复制的文本长度)。
- 翻译功能:将“-”替换为“.”
substr(str,step1,step3) : 在第二个单词和倒数第二个单词之间复制文本。
代码:
data want;
set input;
Sub=translate(substr(str,find(str,scan(str,2,'-')),find(str,scan(str,-1,'-'))-find(str,scan(str,2,'-'))-1),'.','-');
put _all_;
run;
输出:
str=f-2-3-1-5-vcb Sub=2.3.1.5
str=f-2-4-1-6-rtg Sub=2.4.1.6
str=f-2-3-11-1-3-hb17 Sub=2.3.11.1.3
假设我有两个字符串要从 SAS 程序名称转换为 table 数字。
我的目标是将第一个 "f-2-2-7-5-vcb" 转换为“2.2.7.5”。 这应该动态完成。喜欢 "f-2-2-12-1-2-hbd87q", 它需要是“2.2.12.1.2”。
如何实现?
data input;
input str $ 1-20;
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
;
run;
data want;
set input;
Sub=compress(substr(str,3,length(str)),,'kd') ;
run;
有点长,但这对我来说很好。
- 使用 FIND() 查找第一个 '-'
- 使用 REVERSE() 和 FIND() 查找 最后一个 '-'
- 使用 SUBSTR() 和 metrics + math 从上面删除第一个和 最后一个组件
使用 TRANSLATE() 将 - 转换为句点。
z=find(str, '-'); end=find(strip(reverse(str)), '-'); string = translate(substr(str, z+1, length(str) - z - end), ".", "-");
正则表达式只能匹配破折号分隔的数字序列。提取的匹配项可以使用 translate
.
data input;
input str $ 1-20;
rx = prxparse ("/^.*?((\d+)(-\d+)*)/");
if prxmatch(rx,str) then do;
call prxposn (rx,1,s,e);
name = substr(str,s,e);
name = translate(name,'.','-');
end;
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
funky2-2-1funky
f-2-hb17
a2bfunky
;
run;
如果只有数字的令牌序列前面是一个以数字结尾的令牌,或者后面是一个以数字开头的令牌,则会出现一种奇怪的情况。
data input;
input str $ 1-20;
string=translate(prxchange('s/\w+?\-(.*)\-\w+//',-1,strip(str)),'.','-');
datalines;
f-2-3-1-5-vcb
f-2-4-1-6-rtg
f-2-3-11-1-3-hb17
;
run;
您可以在一行中完成此操作。使用 subtr 将文本保留在第二个词和最后一个词之间:
翻译(substr(str,find(str,scan(str,2,'-')),find(str,scan(str,-1,'-'))-find (str,scan(str,2,'-'))-1),'.','-')
- find(str,scan(str,2,'-') : 找到第二个的起始位置 单词。
- find(str,scan(str,-1,'-') : 找到最后一个的起始位置 单词。
- step2 - find(str,scan(str,2,'-'))-1 : 找到第二个的结束位置 最后一个字(要复制的文本长度)。
- 翻译功能:将“-”替换为“.”
substr(str,step1,step3) : 在第二个单词和倒数第二个单词之间复制文本。
代码:
data want;
set input;
Sub=translate(substr(str,find(str,scan(str,2,'-')),find(str,scan(str,-1,'-'))-find(str,scan(str,2,'-'))-1),'.','-');
put _all_;
run;
输出:
str=f-2-3-1-5-vcb Sub=2.3.1.5
str=f-2-4-1-6-rtg Sub=2.4.1.6
str=f-2-3-11-1-3-hb17 Sub=2.3.11.1.3