Quoting?

May 20, 2008
12,171
133
Syracuse, NY, USA
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
12,557
167
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.
 
May 20, 2008
12,171
133
Syracuse, NY, USA
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
12,557
167
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.
 
May 20, 2008
12,171
133
Syracuse, NY, USA
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
 
Aug 23, 2010
688
9
Modern? This behavior is standard for years - grep can signal the success/vailure of the match with errorlevel.
 
May 20, 2008
12,171
133
Syracuse, NY, USA
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
48
1
Atlanta, GA
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.)
 

samintz

Scott Mintz
May 20, 2008
1,555
26
Solon, OH, USA
Perhaps something using DO /P ?
Code:
do r in /p grep 2018 "v:\a b" (echo yes)

But I'm also curious as to why Rex said @EXECSTR is obsolete. The new %(...), %((...)), and %[[...]] V23 commands don't replace it.