Quoting?

#1
The second ECHO command below seems to figure out the quoting OK. But both IF and IFF choke on it. What's up with that?
Code:
v:\> echo 2018xxx > "v:\a b"

v:\> echo "%@execstr[grep 2018 "v:\a b"]"
"2018xxx"

v:\> if "%@execstr[grep 2018 "v:\a b"]" NE "" echo yes
TCC: Syntax error "@execstr[grep 2018 "v:\a"
Usage : IF [/I] [NOT] condition [.AND. | .OR. | .XOR. [NOT] condition ...] command

v:\> iff "%@execstr[grep 2018 "v:\a b"]" NE "" then & echo yes & endiff
TCC: Syntax error "@execstr[grep 2018 "v:\a"
Usage : IFF [NOT] condition [.AND. | .OR. | .XOR. [NOT] condition ...] THEN & commands
yes
TCC: Unknown command "endiff"
 

rconn

Administrator
Staff member
May 14, 2008
10,320
93
#2
TCC is looking to expand the first argument (so IF / IFF can compare it to the next argument). Because you put a quote at the beginning, it terminates at the first white space following the next closing quote. So the first argument is:

"%@execstr[grep 2018 "v:\a

which the variable expansion does not like at all.
 
#3
TCC is looking to expand the first argument (so IF / IFF can compare it to the next argument). Because you put a quote at the beginning, it terminates at the first white space following the next closing quote. So the first argument is:

"%@execstr[grep 2018 "v:\a

which the variable expansion does not like at all.
The expression
Code:
"%@execstr[grep 2018 "v:\a b"]"
works everywhere else I tried it. It's a shame that IF and IFF have to be different.
 

rconn

Administrator
Staff member
May 14, 2008
10,320
93
#4
1) 25+ year old behavior.
2) It works everywhere (not really, but almost everywhere) else because the expression is parsed & expanded before being passed to the command (which won't work for IF / IFF, as they wouldn't have any idea which arguments to compare).
3) IF and IFF have to be different if you want to put variables in your comparisons.
4) Don't use double quotes to delimit your arguments that contain embedded double quotes, and you won't have any problems.
5) Why in the world are you using @execstr to do this? That's (another) obsolete function. It was useful for DOS.
 
#6
Good question! And could you do it otherwise with a single line of code? @EXECSTR is (quite) a convenience; it almost always saves a line or two of code. To avoid @EXECSTR, you'd basically have to do what @EXECSTR does ... send the output of a command to a temp file and check the file. Here, FFIND itself will take care of deleting the temp file.
Code:
alias >&> nul |! ffind /t"=" /f > nul
iff %_ffind_matches == 0 then & echo There are no aliases. & endiff
Note that with the above, the in-process pipe is required because, otherwise, the _FFIND_* variables would be lost.

While these two strategies (below) seem quite different, there's no difference in speed. As noted above, using @EXECSTR involves less typing.
Code:
v:\> type ffindtest.btm
timer /q
do i=1 to 100
        iff "%@execstr[alias >&> nul]" == "" then & noop & endiff
enddo
timer

timer /q
do i=1 to 100
        alias >&> nul |! (ffind /t"=" /f > nul)
        iff %_ffind_matches == 0 then & noop & endiff
enddo
timer


v:\> ffindtest.btm
Timer 1 off: 13:15:53  Elapsed: 0:00:03.12
Timer 1 off: 13:15:56  Elapsed: 0:00:03.12
 
#10
And what if you wanted to assign a line of command output to a variable? I suppose you could do this.

Code:
v:\> function myexecstr `%@exec[@set t=%@unique[%temp]]%@exec[@%2$ > %t]%@line[%t,%1]%@exec[@del /q %t]`

v:\> set zzz=%@myexecstr[0,echo foo^r^nbar^r^nfly] & echo %zzz
foo

v:\> set zzz=%@myexecstr[1,echo foo^r^nbar^r^nfly] & echo %zzz
bar

v:\> set zzz=%@myexecstr[2,echo foo^r^nbar^r^nfly] & echo %zzz
fly
Hmmm! That seems strangely like re-inventing @EXECSTR!
 
Dec 29, 2009
29
0
Atlanta, GA
#11
Interesting discussion!

How would I rewrite the following to get rid of @execstr?
alias wview=view %@EXECSTR[which2 /q %$]

This alias lets me type
C:\> wview SomeBatOrProgName

and it opens up a view of whatever file would have been executed. (I use an external "which" command, which2.exe, because it has a /q flag to cause it to only report the full pathname to the file that would be executed.)