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

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 /?

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

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.

Batch script terminates in case of error when using pipe operator

I need to perferm error handling (check ERRORLEVEL) on an operation involving the pipe operator, but instead of the script continuing with a non-zero ERRORLEVEL, it terminates immediately. How can I avoid this behavior?
Consider the following example. (Note that is a simplified constructed example to illustrate the problem - not a meaningful script)
someinvalidcommand
echo nextline
This will result in
> 'someinvalidcommand' is not recognized as ... command...
> nextline
In other words, the script continues after the error.
Now consider
echo firstline | someinvalidcommand
echo nextline
This will result in only
> 'someinvalidcommand' is not recognized as ... command ...
That is, it terminates before evaluating "echo nextline"
Why this behavior and how to avoid it ? The purpose is to perform something similar to
someoperation | someotheroperation
IF NOT %ERRORLEVEL% == 0 (
handleerror
)
but the error handling has no effect since it stops early.
Delegate it to another cmd instance
cmd /c" someoperation | someotheroperation "
if errorlevel 1 (
handleerror
)

Is it possible to extract emails from a csv using a dos/cmd batch file?

I have a csv file with 1M email addresses and i need to extract them from the CSV to a text file.
I googled this and found very few links, and those that i found, didn't do the trick.
So is it even possible to extract emails from a csv using a dos/cmd batch file?
I now and it is possible to do it with Linux but saddly i'm have to use windows.
Set Arg = WScript.Arguments
set WshShell = createObject("Wscript.Shell")
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
'Remove ^ from quoting command line. Quote, ampersand and brackets
Pttn = Replace(Arg(2), "^(", "(")
Pttn = Replace(Pttn, "^)", ")")
Pttn = Replace(Pttn, "^&", "&")
Pttn = Replace(Pttn, "^""", """")
Set regEx1 = New RegExp
If Instr(LCase(Arg(1)), "i") > 0 then
regEx1.IgnoreCase = True
Else
regEx1.IgnoreCase = False
End If
regEx1.Global = False
regEx1.Pattern = Pttn
Do Until Inp.AtEndOfStream
Line=Inp.readline
Line = RegEx1.Replace(Line, Arg(3))
outp.writeline Line
Loop
To use
cscript //nologo "c:\path to\scriptname.vbs" < inputfile.txt > outputfile.txt
Replace
filter replace {i|n} expression replace
filter repl {i|n} expression replace
Finds and replaces text using regular expressions.
Also used to extract substrings from a file.
Ampersands and brackets in expression must be escaped with the caret. Do not escape carets. Use hexidecimal code \x22 for quotes.
SearchOptions
i - ignore case
n - none
Expression
Regular Expression Reference
Replace
The text to replace. Use $1, $2, $..., $n to specify sub matches in the replace string
Example
filter replace i "=" "No equal sign" < "%systemroot%\win.ini"
This searches for text within square brackets and replaces the line with cat followed by the text within brackets
Filter replace i "^\[^(.*^)\]" "cat$1" < %windir%\win.ini
This searches for any text and prints from the 11th character to the end of the line.
Filter replace i "^.{10}^(.*^)$" "$1" < %windir%\win.ini
This searches a CSV file and prints the second and fourth field
Filter replace i "^.+,^(.+^),.+,^(.+^)$" "$1,$2" < csv.txt
Try a RegEx like (there are thousands on the internet like http://www.regular-expressions.info/email.html)
[0-9a-zA-Z]+\.?[0-9a-zA-Z]?#[0-9a-zA-Z]+\.com|org|net|gov
#set #code=#Batch /*
#echo off
cscript //nologo //E:JScript "%~F0"
goto :EOF
#set #code=#JScript */
var fileContents = WScript.StdIn.ReadAll(),
search = /(\w+)#(\w+)\.(\w+)/g, match;
while ( match = search.exec(fileContents) ) {
WScript.Stdout.WriteLine(match[0]);
}
Copy previous code in a Batch file; for example: GetEmails.bat, and execute it redirecting the input/output files. This is the output of an example session:
C:\> type theFile.txt
Line, with, an, email, address, joedoe#unknown.org
Please, send, mail, to, george#contoso.com, and, someone#example.com, Thanks!
Line, number, 3, with, no, email, address
C:\> GetEmails.bat < theFile.txt
joedoe#unknown.org
george#contoso.com
someone#example.com

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

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

Resources