im generating a CSV from an XLS file with VBA, after that I am filtering the CSV with Batch. My filter looks like this:
for %%a in (*.csv) do (
for /f "usebackq tokens=1-10 delims=, eol=^" %%1 in ("%%a") do (
if %%4 EQU Req_Category ECHO %%1,%%2,%%3,%%4,%%5,%%6,%%7,%%8,%%9 >> "%%a"_JIRA.csv
if %%4 EQU Requirement ECHO %%1,%%2,%%3,%%4,%%5,%%6,%%7,%%8,%%9 >> "%%a"_JIRA.csv
)
)
This works fine if the CSV File has no empty lines.
In rare occasions the XLS -> CSV converting generates empty lines or CRs in the CSV.
SW_Fn-289,4.1.1.1,Controling Hardware PCB,Heading,,,,,IgnoreTesting,
SW_Fn-291,4.1.1.1.0-1,"
Date : 07.03.1777
The SystemDesignSpecification is stored in SVN path
http://sblablablabla.xlsm
",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2,"
Date : 123.123.123
Path : https://apath.com
",Requirement,R1,,New,New,IgnoreTesting,
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
SW_Fn-286,4.2.1,Resource Usage,Heading,,,,,IgnoreTesting,
Every line in the CSV should start with an ID: SW_Fn-Example.
Does every one have an idea how can bring the info on one line with a batch function?
I need to get the file to look like this (before filtering):
SW_Fn-289,4.1.1.1,Controling Hardware PCB,Heading,,,,,IgnoreTesting,
SW_Fn-291,4.1.1.1.0-1,"Date : 07.03.1777 TheSystemDesignSpecificationisstored in SVN path http://sblablablabla.xlsm",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2," Date : 123.123.123 Path : https://apath.com",Requirement,R1,,New,New,IgnoreTesting,
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
SW_Fn-286,4.2.1,Resource Usage,Heading,,,,,IgnoreTesting,
There shouldnt be a line that does not start with SW_Fn-blabla. If a line starts with something else, then it should be a part of the previous line that has an Sw_Fn-blabla.
Then my filter will work to produce this:
SW_Fn-291,4.1.1.1.0-1,"Date : 07.03.1777 TheSystemDesignSpecificationisstored in SVN path http://sblablablabla.xlsm",Requirement,Lab1 (B-Sample),,Released,Accepted,IgnoreTesting,
SW_Fn-4281,4.1.1.1.0-2," Date : 123.123.123 Path : https://apath.com",Requirement,R1,,New,New,IgnoreTesting,
Thanks in advance
try this:
#echo off
for %%a in (*.csv) do (
for /f "delims=" %%b in (%%a) do (
for /f "tokens=4 delims=," %%c in ("%%b") do (
if "%%c"=="Requirement" echo %%b >>%%~na_JIRA%%~xa
if "%%c"=="Req_Category" echo %%b >>%%~na_JIRA%%~xa
)
)
)
read and handle each line complete to overcome the consecutive-delimiter-issue mentioned by Magoo (use another for to check Token4, but don't bother to disassemble and reassemble the complete line)
Aak! don't use numerics for the metavariable (%%1) - it's highly unreliable. Use an alphabetic character.
Batch treats a string of delimiters as a single delimiter and you have nominated commas and spaces as delimiters, so
SW_Fn-166,4.2,Compliance Requirements,Heading,,,,,IgnoreTesting,
would appear as
SW_Fn-166,4.2,Compliance,Requirements,Heading,IgnoreTesting,,,,
You haven't shown what you expect as output. Do you only want the lines that begin SW_Fn- or do you want all lines that don't start SW-Fn appended to the last line that did?
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q36475816.csv"
SET "outfile=%destdir%\outfile.txt"
SET "line="
(
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
SET "newpart=%%a"
IF DEFINED line CALL :test
IF DEFINED line CALL SET "line=%%line%% %%a"
IF NOT DEFINED line SET "line=%%a"
)
IF DEFINED line ECHO(%line%
)>"%outfile%"
GOTO :EOF
:: Test new data " Accumulate data into line or output & start a new line
:test
SET "newpart=%newpart:"=x%"
IF NOT "%newpart:~0,6%"=="SW_Fn-" goto :eof
echo(%line%
SET "line="
GOTO :eof
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q36475816.csv containing your data for my testing.
Produces the file defined as %outfile%
Note that your posted data contains unbalanced quotes in the Fn-4281 item. It's always better to use actual data rather than "somewhere close".
Read each line. If we've already accumulated part of a line, check whether the first few characters are the target. If they are, output the line as constructed and clear line.
If line is clear after this operation, set it to the line read (which must startwith the target, otherwise accumulate the line.
In the :test procedure, remove quotes before testing so that it doesn't break the syntax. Obviously, if the first few characters contains a quote, it doesn't fit the target so the test will correctly detect "no fit"
Your file is actually valid CSV format. Quoted CSV fields may contain any of the following:
comma
quote literal, escaped as ""
newline (either LF or CRLF)
You don't have commas or quotes within your fields, but you do have newlines that are giving your code serious problems.
But that is only one potential problem. Another issue is FOR /F treats consecutive delimiters as a single delimiter, so if any of your desired keeper lines have any empty fields, then your output will be completely wrong.
Batch is inherently far from ideal for any kind of text processing, but for CSV it is especially bad for all but the most simplest problems. If you really want to use batch, you could use ParseCSV.bat to properly parse your CSV and read it using FOR /F in a reliable manner. But there are better options.
PowerShell has an Import-Csv cmdlet. I'm not sure of its capabilities, but if it supports newlines within fields, then you could develop a really slick solution with that.
Another option is my JREPL.BAT regular expression text processor. The following code looks nasty, but it will very efficiently produce your desired output in one step:
jrepl "((?:[\s\S]*?,){3}(?:(Req_Category,|Requirement,)|.*?,)(?:.*?,){4}.*?),[^,\n]*\n?" "$2?$1.replace(/\r\n/g,' ')+'\r\n':''" /m /j /f input.csv /o output.csv
You would need to use CALL JREPL if you put the command within another batch script.
My JREPL solution relies on the fact that none of your input fields contain quoted commas. If it did contain quoted commas, then a JREPL solution would be even more complicated.
This solution works by using the /M multiline option so that I can match across line-breaks.
The search matches each 10 field collection (your 10th field seems to be always empty), regardless of line breaks. $1 contains the first 9 fields (without the trailing comma). $2 contains the 4th field if and only if it matches "Req_Category" or "Requirement". The replacement javascript expression tests if $2 is defined, and if it is, then the whole search expression is replaced with $1 after all newlines have been replaced by spaces, and then a newline is appended. IF $2 is not defined then the whole search expression is replaced with an empty string. Simple in concept, but kind of nasty to develop ;-)
A slight simplification allows you to preserve the original fields containing newlines, and still do the filtering you desire.:
jrepl "((?:[\s\S]*?,){3}(?:(Req_Category,|Requirement,)|.*?,)(?:.*?,){4}.*?),[^,\n]*\n?" "$2?$1+'\r\n':''" /m /j /f input.csv /o output.csv
I was given this code by Aacini (thanks!) but I don't know how to set which text file to search for the data.
#echo off
setlocal EnableDelayedExpansion
set "line=Username:Desired Information</br><br>"
set "string1=Username:"
set "string2=</br><br>"
rem Remove from beginning until string1
set "line=!line:*%string1%=!"
rem Change the string2 by a one character delimiter
set "line=!line:%string2%=|!"
rem Get the desired information
for /F "delims=|" %%a in ("%line%") do set "result=%%a"
echo Result: "%result%"
How would I do this? I'm sure it's just a set textfile=inbox.txt and another line of code to make it use the %TEXTFILE% variable, but I just don't know how.
You don't get the rigth answer because you don't post the right question. Neither in your original question nor in this one you asked for something like "How to read a file and get the text between two strings". Also, you should specify the details of the file and post a section that contain the desired information; otherwise a Batch solution may fail because a large number of factors.
Anyway, I created this simple data file just for testing:
This is a sample file
with unknown format
Previous info. Username:Desired Information</br><br>
End of file
And this is the solution:
#echo off
setlocal EnableDelayedExpansion
set "string1=Username:"
set "string2=</br><br>"
for /F "delims=" %%a in ('findstr "%string1%" file.txt') do (
rem Get the next line
set "line=%%a"
rem Remove from beginning until string1
set "line=!line:*%string1%=!"
rem Change the string2 by a one character delimiter
set "line=!line:%string2%=|!"
rem Get the desired information
for /F "delims=|" %%a in ("!line!") do set "result=%%a"
echo Result: "!result!"
)
Output:
Result: "Desired Information"
However, this solution is prone to fail because multiple reasons, for example:
May the file contain exclamation marks?
May the text that contain the desired information be split in several lines?
May that text contain the "|" choosen separator?
Do you want all instances of the desired information? Or just the first one? Or just the last one?
Etc...
That's because it's parsing specified variables. To read a line from a file
for /f "usebackq tokens=1 delims=" %%A in ("c:\somefolder\somefile.txt") do (
... put your other for loop here
)
See for /? for help. See set /? and call /? (and also for /? again) to see syntax details.
WHERE IS MY FORMATTING AND PREVIEW.
I need to extract information from a path found on a line in a batch file. Specifically the line says:
GLOBP4P=C:\folderx\foldery\folderz\datag.p4p
What I need to extract is the part above identified as "data". The g.p4p is always present, the GLOBP4P is always present, but the things in between can be varying from file to file. I essentially want to strip the g.p4p and then write whatever is left to the first "\" to a variable. in this case the variable would store "data". The problem I have is that "data" can be any number of characters, also there can be any number of path folders, etc.
I attempted to do aFor /f with "\" as a delim to try and break the string apart, but since i don't know how many folders there will be I don't know how to identify taking the last one (i.e. the filename) exclusively.
Thanks
This should work too:
#echo off
for /f "delims=" %%a in ('findstr /i "GLOBP4P=" "file.ini"') do set "var=%%~na"
set "var=%var:~0,-1%"
echo "%var%"
Try this. You will get the LAST occurence finded in your ini file :
#echo off
::The name of the bat file to test
Set $bat="The_ini_file_to_test.ini"
::Finding the string "GLOBP4P" and setting the value in it
for /f %%a in ('findstr /i "GLOBP4P" "%$bat%"') do set %%a
::Getting the first and the Last element of the path
set first=%GLOBP4P:\=&set last=%
::Outputting some results
echo File : [%last%]
echo Data : [%last:~0,-5%]
echo drive : [%first%]
#echo off
set GLOBP4P=C:\folderx\foldery\folderz\datag.p4p
for %%a in ("%GLOBP4P%") do set var=%%~Na
set var=%var:~0,-1%
echo %var%
EDIT: Some explanations added
In a FOR command, %%~N return just the file name of the FOR parameter, in this case is datag string. Enter FOR /? for further details.
When a variable is expanded via %var%, the %var:~START,LEN% notation indicate to extract a substring starting at START character (beginning at zero) and with LEN characters. If LEN have minus sign, indicate the last character backwards from string end. In this case, %var:~0,-1% indicate to extract all but last characters from var, that is, eliminate the last character from datag string. Enter SET /? for further details.
i have to process 300+ HTML files, extract a string from each one and place it in a separate text file for import downstream. upside: the string format is identical in each file and is +/- two lines from the same position as well.
i thought maybe using Python, but then i thought PERL might be a better way since this kinda plays to it's backyard.
sadly, i have no access to UNIX/LINUX or i'd just grep it...
this is such an odd client request that i'm a bit goggle-eyed ATM.
so: what is the best way to extract a target string from a BATCH of files?
WR!
If you give us more details (i.e. path and name of the files, the string you want to extract, etc) perhaps I may write a Windows Batch .BAT file to achieve this task...
EDIT
To write a Batch file that successfully run I need a couple additional data, so I made some assumptions. You may help me to fix the details. This is my method:
Seek for a line that contains ">Text link<". I suppose there is just one; this may be fixed.
Read the next line. I assumed that each td is located in independent lines; this may be fixed.
In this line remove the text from beginning of line until value string.
Replace quotes by $ (the next step cannot process quotes).
Get the text between $; this is the result.
for /F skip... command may read a wrong line if thefile contains empty lines; this may be fixed.
#echo off
setlocal DisableDelayedExpansion
findstr /n ">Text link<" thefile.htm > linefound.tmp
for /F "delims=:" %%a in (linefound.tmp) do set lineNo=%%a
for /F "skip=%lineNo% delims=" %%a in (thefile.htm) do (
set "theLine=%%a"
goto continue
)
:continue
setlocal EnableDelayedExpansion
set theLine=!theLine:*value=!
set theLine=!theLine:"=$!
for /F "tokens=2 delims=$" %%a in ("!theLine!") do set URL=%%a
echo Result: %URL%
EDIT no. 2
You are confusing me. Worked the first code or not? The second example you posted in the comments seems not be related to the first one (is the data within second <td> or after [url=http://?). Is it the same problem or a different one? Please, don't assume I know about HTML file format (I don't). I DO know about Batch files, but I can't guess what to do if I have not complete details...
The following Batch file show everything between square brackets that comes IN THE SAME LINE that have the [url=http:// string in the file given in the first parameter:
#echo off
for /F "tokens=2 delims=[]" %%a in ('findstr /n "[url=http://" %1') do echo %%a
As you're already familiar with Grep, why not use a Windows port, such as the Grep in GnuWin32?
Another great way to get a ton of *nix functionality in Windows is Cygwin http://www.cygwin.com