how to assign the result of a batch command to a variable - batch-file

If on the command line I execute:
c:\digitemp.exe -t0 -o%C -q > res1.txt
res1.txt contains correctly the numerical temperature in Celsius (say: 24.23456). But if the same command is executed inside a bat file (say: test.bat):
#ECHO OFF
ECHO Hola pootol!
ECHO.
c:\digitemp.exe -t0 -o%C -q > res1.txt
rem set pootol = < res1.txt
rem set pootol
ECHO Prem una tecla per sortir.
pause > null
res1.txt contains a wrong Celsius value that I suspect is related to the argument " -o%C ". As you can see I rem the variable assing cause pootol var is wrong assigned with the Celsius value before it is mentioned. What am I doing wrong?

The problem in your case is the % sign, as it's evaluated different in the cmd-line and in batch files.
In batch files you can escape it with doubling it.
So your code looks like
c:\digitemp.exe -t0 -o%%C -q > res1.txt

In batch files % is used to denote variables. So %C is interpreted inside the batch file as a variable and replaced with its value. Since it doesn't have a value it is replaced with an empty string.
Use the caret ^ character to escape the % so that the interpreter treats the % as a normal character.
c:\digitemp.exe -t0 -o^%C -q > res1.txt

Related

Reading 3 consecutive lines with awk? (Or something else)

I have a huge file, and at some point it goes like this:
Bla bla bla
LAST ITERATION: 1780 6 12 0.689655172413793
-8708.81862246834 -8698.33572943212 -2003.09638506407
-9.912281246897692E-003
Bla bla bla
I would like to get all the numbers after "LAST ITERATION:" and put it in a line in a file.
I have managed to get the two first lines with this:
awk 'a && NR==n{ print a,b,c,d,$1,$3 } /LAST ITERATION:/{ a=$3; b=$4; c=$5; d=$6; n=NR+1 }' ./$FOLDER/$NAMEDATA >> $NAMEOUTPUT
But I can't seem to find a way to get the last number which is on the 3rd line. Could anyone help me?
Thanks!
If you are using gawk, where RS can be more than one character, an easier approach would be to use "LAST ITERATION:" as the record separator, and print the first 8 fields of the second record, with a space as the output record seperator:
gawk 'BEGIN{RS="LAST ITERATION:";ORS=" "}NR==2{for(n=1;n<=8;++n)print$n}'
Demo: https://ideone.com/UzwkdN
You might use getline Variable to access future lines, I would use GNU AWK for this task following way, let file.txt content be
Bla bla bla
LAST ITERATION: 1780 6 12 0.689655172413793
-8708.81862246834 -8698.33572943212 -2003.09638506407
-9.912281246897692E-003
Bla bla bla
then
awk '/LAST ITERATION/{getline x1;getline x2;line=$0 " " x1 " " x2;sub(/LAST ITERATION:[[:space:]]+/,"",line);gsub(/[[:space:]]+/," ",line);print line}' file.txt
gives output
1780 6 12 0.689655172413793 -8708.81862246834 -8698.33572943212 -2003.09638506407 -9.912281246897692E-003
Explanation: when LAST ITERATION is encountered I save next line to variable x1 and next next line to variable x2, then construct line from space-sheared current line, next line and next next line, then remove LAST ITERATION: and following whitespaces characters using sub function and alter multiple whitespace characters to single spaces using gsub, after doing that I print said line. Disclaimer: this solution assumes there are always at least 2 lines after line with LAST ITERATION.
(tested in gawk 4.2.1)
If you are using regular awk, you can concatenate the 3 lines starting with the line with LAST ITERATION: to a variable, and split it in the end:
awk 'BEGIN{ORS=" "}/LAST ITERATION:/{n=NR+3}NR<n{s=s$0}END{split(s,a);for(i=3;i<11;++i)print(a[i])}'
If I read your question correctly, you say you want to see an entry within a file, followed by two following lines.
Next to that, you seem to want to work with awk.
My answer is: "Why awk? This can very easily be done using grep.", as follows:
grep has three switches to add more lines, next to the matching one:
-A n : add "n" lines after the match
-B n : add "n" lines before the match
-C n : add "n" lines, combined after and before
So, you can simply use grep -A 2 "match" filename.
Good luck
For batch you can target lines using findstr:
The below can target single lines, consecutive lines or a list of lines.
#Echo off
REM :: CALL %0 <filepath> <integer|integer list>
Set "File.Name="
If exist "%~f1" (
Set "File.Name=%~f1"
)Else (
1>&2 Echo(File Not Found
Exit /B 1
)
If "%~2" == "" (
1>&2 Echo(Missing Arg/s for target Line/s.
Exit /B 2
)
Set Target.Lines=%*
Set "Target.Lines=%Target.Lines:"=%"
For /f "Delims=" %%G in ('CMD /V:ON /C "Echo(!Target.Lines:%~1 =!"')Do Set "Target.Lines=%%G"
Set "Line.Count=0"
Set "Highest.Target=0"
Setlocal EnableExtensions EnableDelayedExpansion
For %%G in (%Target.Lines%)Do if !Highest.Target! LSS %%G Set "Highest.Target=%%G"
Endlocal & Set "Highest.Target=%Highest.Target%"
For /f "Tokens=1* Delims=:" %%G in ('%SystemRoot%\System32\findstr.exe /VNLC:"{false.string[%~n0]}" "%File.Name%"')Do (
Set "Line.Count=%%G"
For %%i in (%Target.Lines%)Do if %%G EQU %%i Echo(%%H
)
If %Line.Count% LSS %Highest.Target% (
1>&2 Echo(Lines missing. Lines in file: %Line.Count%. Highest Target: %Highest.Target%
)
awk '
gsub(/LAST ITERATION:/,""){
gsub(/^ */,"");
o=sprintf("%s ",$0);
while(getline && $1 ~ /^[-]?[0-9]+(\.[0-9]*)?/) {
o=o sprintf("%s ", $0)
}
print gensub(/ */," ", "g", o) > "output_file"
}
' input_file
$ cat output_file
1780 6 12 0.689655172413793 -8708.81862246834 -8698.33572943212 -2003.09638506407 -9.912281246897692E-003

What is the meaning of ':Q=' in variable name in batch cmd

I have the following batch command line:
if not x%COMPUTERNAME%==x%COMPUTERNAME:Q=% (
echo 1
) else (
echo 2
)
What is the meaning of :Q= in the variable COMPUTERNAME
Whatever I enter as value of the variable it always goes to the else block.
%variable:<searchstring>=<replacestring>% replaces one string (in your example Q) with another (in your example an empty string)
The whole if is : "if the variable is the same as when I remove the Q then" or in other words: "is there a Q in the variable?"
Read the help for set /? and if /?

Syntax quirk on assigning a string with parentheses to a variable within an IF block

Below is a BAT file sample which shows a curious behaviour. When a "SET" is used inside () an IF statement we get an error, if we have other code besides a SET then no problem.
I created a work around by doing the SET on the IF line and doing the other logic I need in a normal
IF ... ( stuff ) ELSE ( more )
Does someone know what is going on here?
NB: Same outcome if SETLOCAL is used
::SETLOCAL ENABLEDELAYEDEXPANSION
echo **This works**
#set InstallerTest=false
#IF "%InstallerTest%"=="true" #SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe
#IF NOT "%InstallerTest%"=="true" #SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signfalse.exe
SET SESign_Exe
ECHO **THIS PRODUCES NO ERROR**
#IF "%InstallerTest%"=="true" (
echo IN TRUE PART
) ELSE (
ECHO IN FALSE PART
)
echo **this produces : \Schneider was unexpected at this time.**
#IF "%InstallerTest%"=="true" (
SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe
) ELSE (
SET SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signfalse.exe
)
::ENDLOCAL
Open a command prompt window and execute there cmd /?. At bottom of the last help page output into the console window you can read which characters in strings require surrounding double quotes: the space character and &()[]{}^=;!'+,`~
The reason is easy to understand. The space character is the separator for the "words" (commands, options, parameters, keywords, ...) on command line.
The other characters have special meanings in Windows command line syntax. A not escaped and not in quoted string defined ( marks beginning of a block an ) marks end of a block if not escaped or within a quoted string.
Therefore you need
set "SESign_Exe=%ProgramFiles(x86)%\Schneider Electric\CodeSign\signtrue.exe"
And you should really use always set "variable=value".
See for example answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? for an explanation with an example why using set "variable=value" is always better than using just set variable=value.

if statement when environment variable exists/not exists in batch files

I want to check if a certain environment variable is set in the PC. If yes do x if not do y.
I tried these and some variations of them:
IF EXISTS %SIGN% runtest.exe --redirect -l %NAME%
ELSE runtest.exe -l %NAME%
if "%SIGN%" == "" runtest.exe --redirect -l %NAME%
ELSE runtest.exe -l %NAME%
None of them work well in both cases (when the environment variable SIGN exists and when it doesn't exist).Sometimes just in one case...
Please can you help?
Thanks!
if exists checks for files.
For variables do: if defined sign (without the percent-signs)
IF Conditionally perform a command
IF DEFINED SIGN (
runtest.exe --redirect -l %NAME%
) ELSE (
runtest.exe -l %NAME%
)
or shortly
IF DEFINED SIGN (runtest.exe --redirect -l %NAME%) ELSE (runtest.exe -l %NAME%)
Valid syntax:
all ), ELSE and ( must be on an only line as follows: ) ELSE (
Note:
if DEFINED will return true if the variable contains any value (even if the value is just a space).
According to above predicate, IF DEFINED SIGN condition seems to be equivalent to reformulated test if NOT "%SIGN%"=="" but it is valid in batch only, where %undefined_variable% results to an empty string:
if NOT "%SIGN%"=="" (runtest.exe --redirect -l %NAME%) ELSE (runtest.exe -l %NAME%)
Otherwise, in pure CLI, %undefined_variable% results to %undefined_variable%
Proof:
==>type uv.bat
#echo undefined_variable="%undefined_variable%"
==>uv.bat
undefined_variable=""
==>echo undefined_variable="%undefined_variable%"
undefined_variable="%undefined_variable%"
==>

Batch File Echo a line contains % to a Text File

I'm adding the following line to a Batch file using:
ECHO enter.php?login=%s&pass=%s >>textfile.txt
the Output is coming as
enter.php?login=s
This is my first Batch file.
Double the % - Normally ^ escapes awkward characters like > so to have them reproduced literally, you'd use ^>. % is different - you need %% for each % you want to "print"

Resources