从SAS宏变量中删除最后一个和特定值

时间:2016-05-24 20:17:36

标签: sas

假设我们有一个宏变量:

%let letters = a b c d e f g h i j;

首先,我想从宏变量中删除最后一个字母,并将剩余的字母分配给新的宏变量。其次,我想从宏变量中删除任何给定的字母,并将剩余的字母分配给新的宏变量。我已经编写了两个执行这些操作的宏但是想知道是否有更好的方法可以解决这些问题。大多数其他编程语言都有这种东西的添加/删除功能,但似乎SAS没有 - 这是准确的吗?

第一个宏:

%macro remove_last_letter(macro_var);

    %let letters_no_last = ;

        %do i = 1 %to %sysfunc(countw(&&&macro_var..))-1;
        %let this_letter = %scan(&&&macro_var.., &i.);
            %let letters_no_last = &letters_no_last. &this_letter.;
        %end;

    %put &letters_no_last.;

%mend remove_last_letter;

%remove_last_letter(letters);

的产率:

  

a b c d e f g h i

第二个宏:

%macro remove_a_letter(macro_var, letter_to_remove);

    %let letters_no_spec = ;

        %do i = 1 %to %sysfunc(countw(&&&macro_var..));
        %let this_letter = %scan(&&&macro_var.., &i.);
            %if &this_letter. ~= &letter_to_remove. %then %do;
                %let letters_no_spec = &letters_no_spec. &this_letter.;
            %end;
        %end;

    %put &letters_no_spec.;

%mend remove_a_letter;

%remove_a_letter(letters, c);

的产率:

  

a b d e f g h i j

2 个答案:

答案 0 :(得分:2)

SAS宏语言并不是一种功能齐全的语言。因此,不,它并没有真正用于存储列表,就像我们在现代使用它一样。我真的认为其他语言通常没有专门的功能来删除字符串中的特定单词,这就是你在这里所拥有的;但在SAS中并不是特别难。

第一个我认为如果你使用单个字母,这很简单。

%macro remove_last_letter(macro_var);

  %put %substr(&macro_var.,1,%length(&macro_var.)-1);

%mend remove_last_letter;

如果它不止一个字符当然你需要弄清楚最后一个字符有多长,但你可以使用%sysfunc(countw())来识别这个字并找出它有多长 - 或者你可以找到它字符串中的最后一个空格并使用它来删除它,这可能更容易:

%macro remove_last_word(macro_var);

  %let lastspacepos = %sysfunc(find(&macro_var.,%str( ),1-%length(&macro_var.)));
  %put &=lastspacepos.;  

  %put %substr(&macro_var.,1,&lastspacepos.);

%mend remove_last_word;
%remove_last_word(abc def ghi jkl mno);

对于你的第二部分,我认为TRANWRD是要走的路。

%macro remove_a_letter(macro_var, letter_to_remove);
  %put %sysfunc(tranwrd(&macro_var.,%str( )&letter_to_remove%str( ),%str( )));
%mend remove_a_letter;

%remove_a_letter(a b c d e f g h i j,c);

它当然会删除字符串中的每个 c,而不仅仅是一个,但似乎您希望按照规范进行此操作。

TRANWRD解决方案也可以用于第一个版本,通过使用带有-1参数的SCAN来抓取哪个单词(最右边的单词)然后使用TRANWRD进行空白,如果你知道它是一个唯一的字符。

答案 1 :(得分:1)

看起来你想要删除单词而不是字母。如果您对它们进行编码以使它们可以作为宏函数工作,那么您的宏可能会更有用。

要删除最后一个单词,您只需要知道它有多长。如果列表中至少没有两个单词,则无需返回任何内容。

%macro remove_last_word(list);
%if %sysfunc(countw(&list,%str( ))) > 1 %then
%substr(&list,1,%length(&list)-%length(%scan(&list,-1,%str( ))))
;
%mend remove_last_word;
%put %remove_last_word(a b c d);

如果要删除所有出现的单词,那么TRANWRD()函数就可以了。确保在列表和单词中添加前导和尾随分隔符,使其与列表中较长单词的一部分不匹配。

%macro remove_word(list,word);
%sysfunc(tranwrd(%bquote( &list ),%bquote( &word ),%str( )))
%mend remove_word;
%put %remove_word(a b c d,c);