Output the entire line based on matching string on the command line - windows

I have an input file that looks like:
application database variable value
+-------------------+-------------------+-------------------+-------------------
O_PrTot Rptg ClosedMonthsFY13 Jan:Dec
O_PrTot Rptg OMNICORE_Year FY14
O_PrTot Rptg ClosedMonthsFY14 Jan:Oct
I need to find value for ClosedMonthsFY14 which is Jan:Oct and place this output
into .txt file.
Thanks

Based on your title "Ouput the entire line based on matching string" and your comment "and place this output into .txt file", this should work. We make use of the FINDSTR command, which according to the TechNet article I linked, "searches for patterns of text in files using regular expressions." We don't particularly need a regular expression in this case, but it will work nonetheless:
FINDSTR /I "ClosedMonthsFY14" C:\path\to\input.txt > C:\path\to\output.txt
The switch /I means make the search case-insensitive.

#ECHO OFF
SETLOCAL
FOR /f "tokens=3,4" %%a IN (q27307586.txt) DO IF /i "%%a"=="ClosedMonthsFY14" SET "outstring=%%b"
ECHO %outstring%
FOR /f "delims=" %%a IN ('findstr /i "ClosedMonthsFY14" q27307586.txt') DO SET "outstring2=%%a"
ECHO %outstring2:~61%
GOTO :EOF
I used a file named q27307586.txt containing your data for my testing.
There are two different methods here. The first method relies on the assumption that each column contains exactly one string which does not include separators like spaces or commas.
The second method uses the column-position; 61 characters in the selected line are skipped and the remainder assigned to the variable.
To actually output the variable to a file, simply append >"filename" to the appropriate echo line
Note that the second method will retain the trailing spaces on the line, which may or may not be appropriate for your purpose.
The /i switch in each case makes the string-match case-insensitive.
(Your question header states "the entire line" but your narrative says you need to find the value)

Related

Why are strings from text file cut by the FOR loop on passing them to another function?

Prerequisites
I have a file called urls.txt where I store my URLs, e.g.
www.google.de/test1.yaml?at=refs%2Fheads%2Fmaster
www.google.de/test2.yaml?at=refs%2Fheads%2Fmaster
www.google.de/test3.yaml?at=refs%2Fheads%2Fmaster
My goal
Now I want to loop through these URLs and pass them to another function to download them.
:downloader
FOR /F "delims=" %%i IN (urls.txt) DO (call :sub_function %%i)
goto :eof
:sub_function
echo here url is: %~1
Output
The output is that it cuts off the query strings from the URLs and does not pass them completely to the next function.
For example, the output is: www.google.de/test1.yaml?at
What do I miss?
To protect special characters (like the =-sign in your situation, which constitutes a standard token separator just like SPACE, TAB, , and ;), use quotation for the argument, so it is really treated as one.
Then the call command initiates a second %-expansion phase, which is the reason why the %-signs in your argument cause issues (actually the sequence %2 represents the second argument of your script). To circumvent that problem, store the argument string in a variable and ensure that is is going to be expanded during said second %-expansion phase.
Since URLs may also contain the &-symbol, the argument in the sub-function should not become expanded unquoted in order not to misinterpret it as the command concatenation operator.
Here is the corrected code:
:downloader
FOR /F "delims=" %%i IN (urls.txt) DO (
set "ARG=%%i" & call :sub_function "%%ARG%%"
)
goto :eof
:sub_function
echo here url is: "%~1"

Why are special characters missing in array of lines output by Windows batch file?

I want to insert data (only rows having extended keyword) present in .txt file into Oracle database in the format ID,Data,Date,Project Name where ID, date and project name are present in environment variables.
File.txt has below data:
Writing main object(name=abc)
writing Extended object (name=%abc(123&rest,type=pqr)
logdata.txt should have below data:
A1234C,(name=%abc(123&rest,type=pqr),12022018_11:12:20,DEV:Sales Project
While copying the data, special characters like %,( etc present in the file.txt are missing in the output file logdata.txt.
Please find below code :
set file=D:\MSTR_CICD\file.txt
for /F "usebackq tokens=2*delims=(" %%a in (`findstr "extended" "%file%"`) do (
set /A i+=1
call set array[%%i%%]=%%a
call set n=%%i%%
)
for /L %%i in (1,1,%n%) do call echo %User_ID%,%%array[%%i]%%,%Timestamp%,%proj% >> D:\MSTR_CICD\Batch_Script\logdata.txt
Please correct the code or let me know how can i achieve this. Also, my input file can have any special character as it contain logs of an application.
This batch file can be used for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "proj=DEV:Sales Project"
set "User_ID=A1234C"
set "Timestamp=12022018_11:12:20"
set "InputFile=D:\MSTR_CICD\file.txt"
set "DataFile=D:\MSTR_CICD\Batch_Script\logdata.txt"
if exist "%InputFile%" (
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /I /C:Extended "%InputFile%"') do (
set "DataLine=%%I"
setlocal EnableDelayedExpansion
set "DataLine=!DataLine:*(=(!"
set "DataLine=!DataLine:"=""!"
echo %User_ID%,"!DataLine!",%Timestamp%,%proj%
endlocal
)
) >"%DataFile%"
if exist "%DataFile%" for %%I in ("%DataFile%") do if %%~zI == 0 del "%DataFile%"
:EndBatch
endlocal
FINDSTR runs in the separate command process started by FOR in background with cmd.exe /C a case-insensitive, literal search for the string Extended on the input file and outputs all lines containing this string to handle STDOUT.
FOR captures this output and processes them line by line. FOR ignores empty lines and by default also lines starting with a semicolon because of ; is the default end of line character. And FOR splits up the line into substrings (tokens) using space/tab as delimiter and assigns just the first substring to specified loop variable by default.
By using the FOR option string delims^=^ eol^= an empty list of delimiters and and no end of line character is set to disable line splitting and ignoring lines starting with a semicolon. As this special option string cannot be enclosed in double quotes, it is necessary to escape the space and the two equal signs with caret character to get those three characters outside a double quoted argument string interpreted as literal characters and not as argument string separators.
The entire line as output by FINDSTR found in file is assigned to environment variable DataLine. This is done with delayed environment variable expansion disabled to process also lines correct containing one or more exclamation marks. Otherwise cmd.exe would double parse the line set "DataLine=%%I" after having replaced %%I by the current line and would interpret every ! in the line as begin/end of an environment variable reference resulting in unwanted modification of the line before assigning it to the environment variable.
The usage of command CALL on a line with command SET results also in double parsing the command line before executing the command SET which is the reason why some characters are missing in the environment variables array produced by your code.
For details see also How does the Windows Command Interpreter (CMD.EXE) parse scripts?
After having assigned the line to the environment variable, it is necessary to enable delayed expansion to further process the data line in the FOR loop. That makes the batch file slow, but can't be avoided in this case. Read this answer for details about the commands SETLOCAL and ENDLOCAL.
The first modification on the data line is removing everything left to first (.
The second modification on the data line is replacing all " by "" in the line to escape every double quote according to CSV specification.
Then the remaining data line is output together with the other data enclosed in double quotes as the data line can contain also one or more commas which requires according to CSV specification that the data is enclosed in double quotes.
For CSV specification read for example the Wikipedia article about comma-separated values.
Everything output by ECHO inside FOR loop is redirected to the specified data file which overwrites a by chance already existing data file with same name.
It is possible that FINDSTR does not find any line containing Extended in any case resulting in producing a data file with 0 bytes. The empty data file is deleted by the second FOR.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
set /?
setlocal /?

How to find particular contents in list of files

Please can someone tell how to find particular pattern in list of files.
I use the command:
dir *.txt /b /s >> C:\Users\Amrendra\Downloads\NIT_Testing\fileList.txt
In fileList.txt I have a list of files.
Now I want to find a certain pattern say abc in all the files listed.
So I want each line containing that pattern to be written into a new file.
Please suggest as I am completely new to batch command.
Thanks
I'm not sure if I got you completely right. You've echoed the names of all .txt files from some folder into one text file. Now you want to check it line by line for filenames containing some substring in the file name. Is that correct? If it is, here is the solution:
#ECHO OFF
SET targetFile=C:\Some\Path\SomeTextFile.txt
SET sourceFile=C:\Some\Path\Source.txt
SETLOCAL EnableDelayedExpansion
TYPE NUL>%targetFile%
FOR /F "tokens=*" %%L IN (sourceFile) DO (
SET templine=%%L
SET templine=!templine:abc=!
IF NOT !templine!==%%L (
ECHO %%L>>%targetFile%
)
)
Let's take a look on how it works: first we put the path to the file containing the file names into the variable %sourceFile% and the path to the target file into the variable %targetFile%. We need EnableDelayedExpansion to be able to work with changing variables inside the FOR-loop. TYPE NUL>%targetFile% simply clears the target file in case there are some entries from former runs.
The main work is done inside the FOR-loop. We read the source file line by line and want to check if the line contains the substring we are looking for. To do this we first store the line (%%L) in a temporary variable. Then we replace any occurrences of the search string with an empty string, means we simply remove abc from the temporary string. Finally we compare our modified temporary string with the original one. If they are equal we can be sure that the serch string abc was not in the original string. The other way around, if the strings differ, the substring was in the original string. So in the second case we do ECHO %%L>>%targetFile% which means we write the whole file name containing the search substring into our target file. Et voilĂ , we're done!
EDIT: As you want to search all listed files for the substring, here the new code:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET sourceFile=C:\Users\Amrendra\Downloads\NIT_Testing\fileList.txt
SET targetFile=C:\Users\Amrendra\Downloads\NIT_Testing\newList.txt
SET searchString=abc
TYPE NUL>%targetFile%
FOR /F "tokens=*" %%L IN (%sourceFile%) DO (
FINDSTR %searchString% "%%L">NUL
IF !ERRORLEVEL!==0 ECHO %%L>>%targetFile%
)
Here we are using findstr to check if a text file contains the string we are searching. As findstr usually would output the line which contains the searched string (which we don't want) we simply mute the command using >NUL. What we actually need is the ERRORLEVEL! If the string was found in a file findstr will set ERRORLEVEL to 0 or to 1 otherwise. So the only thing we have to do is to check if !ERRORLEVEL!==0.

Delete a Batch file variable in a text file

I am currently trying to delete a variable from a batch file which is in a text file
e.g. delete %variable%
where %variable% = "test"
So the batch script would delete the instance of "test" in the specified text file
Can this be done?
#echo off
setlocal enabledelayedexpansion
set variable=test
for /f "delims=" %%l in (foo.txt) do (
set "line=%%f"
echo !line:%variable%=!
)
To avoid potential special character issues with the string you are searching for, it may be better to just call findstr directly like this:
type input.txt | findstr /b /e /v "remove_line" > input_without_remove_line.txt
/b and /e together will only match if the "remove_line" is the only text on a line. /v will switch the output to only print all lines that do not match.
If you are sure you're not passing special characters, it is pretty easy to wrap that in a small batch and replace remove line with %1 or %* to use your passed parameters.
Unfortunately, you will need to use a temporary file - replacing the file in place doesn't work with the DOS output redirection.
If you were wanting to delete all instances of a specified word within any line, batch and findstr are probably not the way to do it. Look at sed, which can do much more and is freely available. If you can't install another utility, even vbscript using cscript would be a better way to do this than batch.

Defining these batch commands

Over the past few years I've really found Stackoverflow to be very helpful, and decided to create an account - this is my first post.
Example situation - I have a fair few of these images, of different subjects -
AAA_BBB_randomDigits_front.jpg
AAA_BBB_randomDigits_left.jpg
AAA_BBB_randomDigits_right.jpg
ZZZ_EEE_randomDigits_front.jpg
ZZZ_EEE_randomDigits_left.jpg
ZZZ_EEE_randomDigits_right.jpg
I would like them to all be grouped up in folders as -
AAA_BBB_randomDigits\(contains left, front and right)
ZZZ_EEE_randomDigits\(contains left, front and right)
The code I currently have works -
#echo off
for /f "tokens=1-3 delims=_" %%a in ('dir /b /a-d *_*_*_*.*') do (
md "%%a_%%b_%%c" 2>nul
move "%%a_%%b_%%c*" "%%a_%%b_%%c"
)
pause
However, I would love it if someone could explain to me -
What's %%a?
What's dir /b /a-d and why do I need it?
Is it neccessary to have #echo off and pause?
Thanks guys, I really appreciate it.
For documentation, see commandname /? from the prompt.
dir /b /a-d filemask performs a directory listing /b specifies filenames only - no size, date, header or footer. The /a-d excludes directorynames.
You need it to provide the names to the for /f command.
for /f reads the "filename" in parentheses (it can be a real filename or a single-quoted command (like dir) or a double-quoted literal string) and assigns values to the metavariable (in this case, %%a) according to the specified options (the part in quotes directly following the /f).
The delims option specifies which set of characters is used for parsing the line of data arriving from the "file" specified. The line is then interpreted as a series of tokens, separated by delimiter-sequences. By default, delims is Space and Tab. It's common to turn delims off entirely using "...delims=" in which case, there is but one token (the entire line). Note that any characters between delims= and " are equally-ranking and case-sensitive - it is a set of delimiters which replaces Space and Tab, not a delimiter-string.
The tokens option specifies which tokens are selected, by number, starting at 1. The special token * means "the remainder of the line following the highest-number token specified (including any delimiter characters)". By default, tokens=1.
%%a is a metavariable. It is the variable that holds the first token number selected from the tokens= list. Each selected token number is assigned to the next metavariable name in alphabetical sequence, hence in your example, since you have tokens=1-3 then %%a is the first token, %%b the second and %%c the third. Metavariables are always one letter (some other characters are sometimes used - but numerics are definitely not allowed) and the name is case-sensitive (normally, batch is case-insensitive). %%a, %%A and %a% are all different variables. %a% and %A% are the same variable.
A metavariable is only valid within the for loop where it was created. When the for loop ends, the variable disappears.
#echo off simply turns off the command-echoing that batch would otherwise produce (show the command on the console, then execute it). It's used to reduce clutter on the display. When debugging a section of code, it's normal to set echo to on (echo on) and then off again (echo off) to show precisely what instructions are being executed. The # means "don't report this command to the console"
The pause simply waits until a response is received from the keyboard. It's used to allow the display to be read rather than simply continuing directly to the next instruction. It's often used in debugging and also to allow the result of a batch to be held for the user if the batch is executed by using point-click-and-giggle.

Resources