如何在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),'.','-')

  1. find(str,scan(str,2,'-') : 找到第二个的起始位置 单词。
  2. find(str,scan(str,-1,'-') : 找到最后一个的起始位置 单词。
  3. step2 - find(str,scan(str,2,'-'))-1 : 找到第二个的结束位置 最后一个字(要复制的文本长度)。
  4. 翻译功能:将“-”替换为“.”

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