<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic SAS / Macro: Expected close parenthesis in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740212#M231172</link>
    <description>&lt;P&gt;When I use the following in a macro, I get an ERROR: message:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;3    %let list1 = a b ;
4    %let list2 = b c ;
5
6    %let list = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1. &amp;amp;list2.)))" ;
7    %put &amp;amp;list. ;
"a" , "b" , "b" , "c"
8
9
10
11   %macro tmp ;
12
13                    data __dedup ;
14                      do var = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1.
14 !  &amp;amp;list2.)))" ;
ERROR: Expected close parenthesis after macro function invocation not found.
15                        if var ne " " then output ;
16                      end ;
17                    run ;
18   %mend ;
19
20
21   %tmp ;
ERROR: Expected close parenthesis after macro function invocation not found.

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.__DEDUP may be incomplete.  When this step was stopped there were 0
         observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;I would appreciate any insight, references, or solutions.&amp;nbsp; Note that I remove single and double quotation marks in a prior step.&amp;nbsp; We are using "traditional" SAS variable names only, but that will make an interesting challenge to address.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Kevin&lt;/P&gt;</description>
    <pubDate>Mon, 10 May 2021 15:29:45 GMT</pubDate>
    <dc:creator>Kevin_Viel</dc:creator>
    <dc:date>2021-05-10T15:29:45Z</dc:date>
    <item>
      <title>SAS / Macro: Expected close parenthesis</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740212#M231172</link>
      <description>&lt;P&gt;When I use the following in a macro, I get an ERROR: message:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;3    %let list1 = a b ;
4    %let list2 = b c ;
5
6    %let list = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1. &amp;amp;list2.)))" ;
7    %put &amp;amp;list. ;
"a" , "b" , "b" , "c"
8
9
10
11   %macro tmp ;
12
13                    data __dedup ;
14                      do var = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1.
14 !  &amp;amp;list2.)))" ;
ERROR: Expected close parenthesis after macro function invocation not found.
15                        if var ne " " then output ;
16                      end ;
17                    run ;
18   %mend ;
19
20
21   %tmp ;
ERROR: Expected close parenthesis after macro function invocation not found.

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.__DEDUP may be incomplete.  When this step was stopped there were 0
         observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;I would appreciate any insight, references, or solutions.&amp;nbsp; Note that I remove single and double quotation marks in a prior step.&amp;nbsp; We are using "traditional" SAS variable names only, but that will make an interesting challenge to address.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Kevin&lt;/P&gt;</description>
      <pubDate>Mon, 10 May 2021 15:29:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740212#M231172</guid>
      <dc:creator>Kevin_Viel</dc:creator>
      <dc:date>2021-05-10T15:29:45Z</dc:date>
    </item>
    <item>
      <title>Re: SAS / Macro: Expected close parenthesis</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740217#M231174</link>
      <description>&lt;P&gt;What I strongly suspect is happening is that the DO&amp;nbsp; will accept character values in a list:&lt;/P&gt;
&lt;PRE&gt;data example;
   do var= "A","B","X";
      output;
   end;
run;&lt;/PRE&gt;
&lt;P&gt;So your&lt;/P&gt;
&lt;LI-CODE lang="sas"&gt; do var = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1.
14 !  &amp;amp;list2.)))" ;&lt;/LI-CODE&gt;
&lt;P&gt;is two pieces of text:&lt;/P&gt;
&lt;P&gt;"%sysfunc( prxchange( s/\s+/%str("&lt;/P&gt;
&lt;P&gt;and&lt;/P&gt;
&lt;P&gt;")/ , -1 , %nrbquote(&amp;amp;list1.&amp;amp;list2.)))"&lt;/P&gt;
&lt;P&gt;So the 'functions' aren't closed /opened properly.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I can't tell what you are attempting to provide an alternate but question the need for the %str, or at least why it is there.&lt;/P&gt;</description>
      <pubDate>Mon, 10 May 2021 15:54:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740217#M231174</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2021-05-10T15:54:16Z</dc:date>
    </item>
    <item>
      <title>Re: SAS / Macro: Expected close parenthesis</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740225#M231178</link>
      <description>&lt;P&gt;Thank you for the response.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Consider this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;4229  %let list1 = a b ;
4230  %let list2 = b c ;
4231
4232  data __dedup ;
4233    do var = "%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1. &amp;amp;list2.)))" ;
4234      if var ne " " then put var= ;
4235    end ;
4236  run ;

var=a
var=b
var=b
var=c
NOTE: The data set WORK.__DEDUP has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.00 seconds
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;I am taking a list of SAS variables and quoting them and placing commas between them.&amp;nbsp; A B will be "A" , "B".&amp;nbsp; I already removed possible quotation marks (single and double) and commas.&amp;nbsp; I need to mask the comma in the regex, so I used the %STR() function.&amp;nbsp; I am protecting against a user submitting the same variable in both lists, so I de-dup it.&amp;nbsp; I figured the SQL (or SORT) procedure has a trusted way, so I needed to put the variables as values of a variable in a SAS data set. This seemed like an obvious approach.&amp;nbsp; This must be an issue with the macro compiler, since it works fine above.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If I were to use SAS code and not macro, then the quotation mark would "protect" the comma:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;4344  data __dedup ;
4345    var = prxchange( 's/\s+/" , "/'
4346                   , -1
4347                   , "A B"
4348                   ) ;
4349    put var= ;
4350  run ;

var=A" , "B
NOTE: The data set WORK.__DEDUP has 1 observations and 1 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.00 seconds
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This, also, was perplexing (at least from my level of understanding):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;4250  %let list1 = %sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1.))) ;
4251  %put &amp;amp;list1. ;
a" , "b
4252
4253  %let list2 = %sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list2.))) ;
NOTE: Line generated by the macro function "SYSFUNC".
1      b" , "c
        -----
        49
NOTE 49-169: The meaning of an identifier after a quoted string might change in a future SAS release.  Inserting white space
             between a quoted string and the succeeding identifier is recommended.

4254  %put &amp;amp;list2. ;
NOTE: Line generated by the macro variable "LIST2".
1      b" , "c
        -----
        49
b" , "c
NOTE 49-169: The meaning of an identifier after a quoted string might change in a future SAS release.  Inserting white space
             between a quoted string and the succeeding identifier is recommended.&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Specifically, white space follows the double quotation mark; I purposefully inserted it.&amp;nbsp; Quizzically, the first statement does not generate the code.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Kind regards,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Kevin&lt;/P&gt;</description>
      <pubDate>Mon, 10 May 2021 16:20:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740225#M231178</guid>
      <dc:creator>Kevin_Viel</dc:creator>
      <dc:date>2021-05-10T16:20:20Z</dc:date>
    </item>
    <item>
      <title>Re: SAS / Macro: Expected close parenthesis</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740234#M231184</link>
      <description>&lt;P&gt;The error message is pretty straight forward. It is from SYSFUNC saying it did not see the double right parentheses you normally need in a expression like&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%sysfunc(sasfunc())&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;So why does it work in open code and fail in macro code?&lt;/P&gt;
&lt;P&gt;Let's look at your %sysfunc() call:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;"%sysfunc( prxchange( s/\s+/%str(" , ")/ , -1 , %nrbquote(&amp;amp;list1.    &amp;amp;list2.)))" &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The issue is that inside a macro the parsing is getting confused by have the quotes macro quoted.&amp;nbsp; So just remove those.&amp;nbsp; You only need to quote the comma.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;"%sysfunc( prxchange( s/\s+/" %str(,) "/ , -1 , %nrbquote(&amp;amp;list1.    &amp;amp;list2.)))" ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If you do want to use %STR() to macro quote the quotes then add % in front of each.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;"%sysfunc( prxchange( s/\s+/%str(%" , %")/ , -1 , %nrbquote(&amp;amp;list1.    &amp;amp;list2.)))" &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Or use BQUOTE().&amp;nbsp; Also I am not sure why you are using NRBQUOTE() in the other place.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;"%sysfunc( prxchange( s/\s+/%bquote(" , ")/ , -1 , %bquote(&amp;amp;list1.    &amp;amp;list2.)))" &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;If you want to keep the issue in macro code then just make some deduping logic of your own.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%macro dedupvars(varlist);
%local newlist i newvar;
%do i=1 %to %sysfunc(countw(&amp;amp;varlist,%str( )));
  %let newvar=%scan(&amp;amp;varlist,&amp;amp;i,%str( ));
  %if not %sysfunc(indexw(%upcase(&amp;amp;newlist),%upcase(&amp;amp;newvar))) %then
    %let newlist=&amp;amp;newlist &amp;amp;newvar
  ;
%end;
&amp;amp;newlist.
%mend dedupvars;
%put %dedupvars(A b c a B C e);&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 10 May 2021 17:47:47 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740234#M231184</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2021-05-10T17:47:47Z</dc:date>
    </item>
    <item>
      <title>Re: SAS / Macro: Expected close parenthesis</title>
      <link>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740477#M231317</link>
      <description>&lt;P&gt;Tom,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp; As usual, an excellent reply with plenty of educational points.&amp;nbsp; With more than 20 years of doing it, being wrong on the internet about SAS still stings &lt;span class="lia-unicode-emoji" title=":slightly_smiling_face:"&gt;🙂&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp; I violated one of my rules: mask nothing more than required.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp; I think that I used %NRBQUOTE() out of habit of quoting strings that might have, by bad practice, certain tokens, like % or &amp;amp;, even if the values might not be valid (I might have a error check for well-formed values at the beginning of a macro, but I carry it through).&amp;nbsp; Also, I read Ian Whitlock's quoting papers (and posts) periodically, but I should probably read them again.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp; I like the elegance of your wholly macro approach to dedup the list.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Kevin&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 11 May 2021 14:34:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/SAS-Macro-Expected-close-parenthesis/m-p/740477#M231317</guid>
      <dc:creator>Kevin_Viel</dc:creator>
      <dc:date>2021-05-11T14:34:19Z</dc:date>
    </item>
  </channel>
</rss>

