Windows Batch Script parsing multiline file with variable line formats? - windows

I need to parse a file that has the following format:
A + tags/RWSTestConsole_tag1/
(from trunk/RWSTestConsole/:r776)
So I'm using a FOR /F loop with a counter and inspecting the tokens based on whether I'm looking at line 1 or line 2. Everything works fine except the first token for line 2 includes the leading spaces (" from") and a) I thought the delims on my FOR would take care of spaces and b) theoretically I could just compare to a constant string that is set to " from" but that's kind of hokey.
This is my FOR command:
for /F "tokens=1,2,3,4,5 delims=():/ " %%a in (svn.txt) DO (
Is there a change I can make to the FOR command to ignore the spaces? If not is there a way to trim the token inside the FOR loop's DO clause so I only get the word without the leading spaces?
Edit:
This is output from a Subversion SVNLOOK command in a script that is managing whether or not to allow a "tag" to be created. The output can be 1 line that must be formatted as:
D /tags/tagfoldername/
If it's one line but it's not a delete for the actual tag folder then it's an error. This case is handled.
If it's more than 2 lines it's a list of files and that's an error. I have that handled.
The case I'm having problems with is if it is 2 lines it needs to be in the format shown above:
A + tags/RWSTestConsole_tag1/
(from trunk/RWSTestConsole/:r776)
Where col 1 = "A". col 3 = "+", col 5 = "tags" and the remainder of line one is the tag folder name. The second line is the source of the create request so it has to start with "from", followed by "trunk", "branches" or "tags" followed by a single-level folder name and a revision number.
I used the FOR command as described above. In the DO clause I look at a counter to tell if I'm parsing line 1 or line 2. Line 1 is simple, I have all the logic to handle it.
Line 2 is parsed by the same FOR command and the first token (%%a) removes the "{" from delims, but leaves behind all the leading blanks so I get back %%a=" from".
I need to know if there's a way I can modify the FOR command to remove the blanks or a way to trim %%a within the FOR DO clause to remove the blanks.
Edit 2: FOR Loop Code
set c=1
for /F "tokens=1,2,3,4,5 delims=():/ " %%a in (svn.txt) DO (
echo op=%%a, %%b, %%c, %%d, %%e
if !c!==1 (
set rc1=0
if /I %%a EQU A (
if "%%b" EQU "+" (
if [%%e] EQU [] (
echo Tag from a Copy Op
set rc1=0
) else (
echo Found a subfolder: %%e - not a tag delete
set rc1=1
)
) else (
echo Tag not a Copy
set rc1=1
)
)
)
if !c!==2 (
set rc2=0
set str1=%%a
echo String replace 1 = !str!
set str2=!str1:~-4!
echo String Replace 2 *!str2!*
if /I !str2! EQU FROM (
set isvalid=false
if %%b EQU trunk set isvalid=true
if %%b EQU branches set isvalid=true
if %%b EQU tags set isvalid=true
if !isvalid! EQU true (
set rc2=0
) else (
set rc2=1
echo Invalid source for Tag Creation
)
) else (
set rc2=1
echo Tag not FROM
)
)
set /a c+=1
)
echo RC1=!rc1!
echo RC2=!rc2!
set /a rc=!rc1!+!rc2!
echo final RC = !rc!

Related

Insert a string in a fixed position in a text file

I need to insert 4 strings in a text file in a fixed position:
first string: the product, at the beginning of the line, column 1
second one: %%b, column 20
third one: %%c, column 33
fourth one: doesn't exist, column 42.
I always want the strings written at the exact same position no matter how longer are the other strings before. so it should looks like the example below:
the product ergerzgtrg 65ggrth784rjhnjgbkljn doesn't exist
the product reggbrtbhtrergzthrjhlyoiul rtjntjrez doesn't exist
the product zef rt doesn't exist
Here's my code:
FOR /F "delims=; tokens=1-7*" %%a in (mytextfile.txt) do (
if "%%e"=="Unkown" (
echo the product %%b %%c doesn't exist>>Unkown_product.txt
)
)
mytextfile.txt looks like this:
K5134908-Blabla_4;K5134908;Blabla_4;01-69423;Unkown;K5134908-Blabla_4-516245;K5134908-Blabla_4-516245;
K2602207-Blabla_2;K2602207;Blabla_2;01-81111;Unkown;K2602207-Blabla_2-516245;K2602207-Blabla_2-516245;
K2602006-Blabla_3;K2602006;Blabla_3;01-82789;Unkown;K2602006-Blabla_3-516245;K2602006-Blabla_3-516245;
K2601507-Blabla_4;K2601507;Blabla_4;01-75135;Unkown;K2601507-Blabla_4-516245;K2601507-Blabla_4-516245;
Is there any way to do that within a batch file (.bat)?
Add enough spaces to the values (20 in my example), then cut the first [whatever you need] characters (15 in my example):
#echo off
setlocal
FOR /F "delims=; tokens=1-7*" %%a in (mytextfile.txt) do (
if "%%e"=="Unkown" call :format "%%b" "%%c"
)
goto :eof
:format
set "b=%~1 "
set "c=%~2 "
set "b=%b:~0,15%"
set "c=%c:~0,15%"
echo the product %b% %c% doesn't exist>>Unkown_product.txt
Note: the search string is "Unkown" according to your file example (probably a typo, I guess it should be "Unknown")

Windows Batch - Find word in one string matching word in another string and capture output

While this may seem easy to some, I've struggled for hours on it.
I have a file:
MYFOLDER,JobE,JobD_ENDED_OK,
MYFOLDER,JobD,JobC_ENDED_OK,JobD_ENDED_OK
MYFOLDER,JobD,JobB_ENDED_OK,
MYFOLDER,JobC,JobA_ENDED_OK,JobC_ENDED_OK
MYFOLDER,JobB,JobA_ENDED_OK,JobB_ENDED_OK
MYFOLDER,JobA,,JobA_ENDED_OK
I need to loop through and find where token 4 in one line matches token 3 in another line and then echo a statement to a file. I am looking for an output file that shows this:
MYFOLDER_JobA_MYFOLDER_JobB matches JobA_ENDED_OK
MYFOLDER_JobA_MYFOLDER_JobC matches JobA_ENDED_OK
MYFOLDER_JobB_MYFOLDER_JobD matches JobB_ENDED_OK
MYFOLDER_JobC_MYFOLDER_JobD matches JobC_ENDED_OK
MYFOLDER_JobD_MYFOLDER_JobE matches JobD_ENDED_OK
I know it's a FOR loop with a DO, I am just not getting the rest of it.
Any assistance is greatly appreciated.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q46510665.txt"
SET "outfile=%destdir%\outfile.txt"
(
FOR /f "usebackqdelims=" %%h IN ("%filename1%") DO (
SET "col4line=%%h"
SET "col4line=!col4line:,=|,|!"
FOR /f "tokens=1-4delims=," %%a IN ("!col4line!") DO IF "%%d" neq "|" (
FOR /f "usebackqdelims=" %%H IN ("%filename1%") DO (
SET "col3line=%%H"
SET "col3line=!col3line:,=|,|!"
FOR /f "tokens=1-4delims=," %%A IN ("!col3line!") DO (
IF "%%d|"=="%%C" (
SET "reportline=%%a_%%b_%%A_%%B matches %%C"
ECHO !reportline:^|=!
)
)
)
)
)
)>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q46510665.txt containing your data for my testing.
Produces the file defined as %outfile%
For each line in the file, set a variable col4line to the entire line via %%h, then replace each , with |,| so that successive , will be separated. Tokenise on , and ignore any line which has simply | as its 4th token (ie last-column-empty).
Repeat the process for every line in the file this time through %%H into col3line (note case differential to use different actual metavariables) and if the third column matches the fourth column+| from the outer loop, assemble the report line from the tokens and output, removing the |s.

How to delimit fixed width text file based upon column number

I have text file which is fixed width. I need to delimit the contents based upon the Column number ( Column 100-120 ) into a variable and need to check length of the variable.
There are chance that variable has more than 20 character and i need to remove that particular line
Eg :
0 1 2 3 4 5 6 7 8 9 0
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
short_name des_shrt px
BOS1111 ALTIC 6.62 2_23 106.37500000
BOS2222 AMA 47.26000000
BOS3333 AMB 12.898000
BOS4444 AMEX Express 10.09780000
BOS5555 BBC 111.2233
BOS6666 CNN 123.123445
BOS7777 STACK OVERFLOW 344.9090
BOS8888 STACT 12.0 2/1988 10.99999999
BOS9999 ABC 20
Output :
px
106.375
47.26
12.898
10.0978
111.2233
123.123445
344.909
10.99999999 -> it exceeds 10 digit and should throw error
20
Here is a pure batch-file solution – see all the explanatory remarks in the code:
#echo off
setlocal EnableDelayedExpansion
rem // Define constants here:
set "_FULL_LINES_OUT=#"
rem // Initialise variables:
set "HEAD=#"
rem // Read text file line by line:
for /F "usebackq delims=" %%L in ("%~1") do (
rem // Store current line into environment variable:
set "LINE=%%L"
rem // Extract 12 characters at character position 58:
set "LINE=!LINE:~58,12!"
rem // Remove trailing spaces, if any:
for /F %%K in ("!LINE!") do set "LINE=%%K"
rem // Check whether line is the first one (header):
if defined HEAD (
rem // Return header line:
if defined _FULL_LINES_OUT (echo %%L) else (echo !LINE!)
set "HEAD="
) else (
rem // Split numbers into integer and fractional parts:
for /F "tokens=1* delims=." %%I in ("!LINE!") do (
set "INT=%%I" & set "FRACT=%%J"
)
rem // Remove trailing zeros from fractional part:
set "FLAG=#"
for /L %%J in (1,1,12) do (
if defined FLAG (
if "!FRACT:~-1!"=="0" (
set "FRACT=!FRACT:~,-1!"
) else (
set "FLAG="
)
)
)
rem // Reassemble truncated decimal number:
if defined FRACT (
set "LINE=!INT!.!FRACT!"
) else (
set "LINE=!INT!"
)
rem // Check whether string length of number exceeds 10:
if not "!LINE:~10!"=="" (
rem // Number is longer than 10 characters:
>&2 (if defined _FULL_LINES_OUT (echo %%L) else (echo !LINE!))
) else (
rem // Number is not too long, so return original line:
if defined _FULL_LINES_OUT (echo %%L) else (echo !LINE!)
)
)
)
endlocal
exit /B
Supposing you name the script check-px-numbers.bat and your data file is called D:\Data\data.txt, run the script like this:
check-px-numbers.bat "D:\Data\data.txt" 2> nul
To write the output into another file D:\Data\filtered.txt, call the script like this:
check-px-numbers.bat "D:\Data\data.txt" > "D:\Data\filtered.txt"
This would return the following output file when using your sample data:
short_name des_shrt px
BOS1111 ALTIC 6.62 2_23 106.37500000
BOS2222 AMA 47.26000000
BOS3333 AMB 12.898000
BOS4444 AMEX Express 10.09780000
BOS5555 BBC 111.2233
BOS6666 CNN 123.123445
BOS7777 STACK OVERFLOW 344.9090
BOS9999 ABC 20
And the following error message would appear in the console window:
BOS8888 STACT 12.0 2/1988 10.99999999
Change the line set "_FULL_LINES_OUT=#" to set "_FULL_LINES_OUT=" (or remove it) if you want your output data to look like this:
px
106.375
47.26
12.898
10.0978
111.2233
123.123445
344.909
20
In case you want to overwrite the original file, you need to do that in two steps:
check-px-numbers.bat "D:\Data\data.txt" > "D:\Data\filtered.txt"
> nul move /Y "D:\Data\filtered.txt" "D:\Data\data.txt"
To write the erroneous lines into a file, use this:
check-px-numbers.bat "D:\Data\data.txt" 2> "D:\Data\errors.txt"
You can combine this to write the filtered and the error lines at once like this:
check-px-numbers.bat "D:\Data\data.txt" > "D:\Data\filtered.txt" 2> "D:\Data\errors.txt"

batch replace spaces between quotes in file and then remove all quotes

I want create a batch to replace spaces with a + sign if the space is in between quotes. Then I want to remove the quotes from a text file. How can I accomplish this?
So I want to change a line like this:
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" "-" www.vietnam.ttu.edu 200 200 200 1868 0
To this line.
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 facebookexternalhit/1.1+(+http://www.facebook.com/externalhit_uatext.php) - www.vietnam.ttu.edu 200 200 200 1868 0
Thanks
You could use JREPL.BAT to arrive at a very concise and efficient solution. JREPL is a pure script based (JScript/batch) regular expression text processing utility that runs on any version of Windows from XP onward.
jrepl "\q| " "q=!q;''|q?'+':' '" /j /x /t "|" /jbegln "q=false" /f test.txt /o -
For this solution I use the /T option, which is very similar to the unix tr utility, or the sed y command.
I define two search terms, the first for a quote (The \X option enables the \q escape sequence), and the second for a space.
The /J option treats replacement strings as JScript. The first replacement string for the quote toggles a "q" variable TRUE or FALSE, and replaces the quote with an empty string. The second replacement string conditionally replaces the space with a plus or space, depending on the state of the "q" variable.
The /JBEGLN option initializes the "q" variable to FALSE at the beginning of each line.
The /F option specifies the input file, and the /O - option specifies that the output overwrites the original file.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q34732271.txt"
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO ECHO %%a&SET "line="&CALL :process %%a
GOTO :EOF
:process
SET "addition=%~1"
IF not DEFINED addition ECHO %line:~1%&GOTO :eof
IF "%~1"==%1 (
REM quoted
SET "line=%line% %addition: =+%"
) ELSE (
SET "line=%line% %addition%"
)
shift
GOTO process
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q34732271.txt containing your data for my testing.
The echo %%a shows your one line of data on the screen and the echo within the :process routine shows that line processed.
Batch is not an ideal language to process strings as it exhibits sensitivity to many symbols. This process should work provided you are happy to have space-strings compressed and the source string does not contain , ;,tab % or any other symbol that cmd treats specially.
Here is a pure batch-file solution that walks through the characters in each line in file line.txt, replaces all SPACEs in between a pair of quotation marks "" by + signs and stores the result in text_new.txt. The input string may contain any characters, even special ones:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define global constants here:
set "INFILE=line.txt"
set "OUTFILE=line_new.txt"
set "SEARCH= "
set "REPLACE=+"
set "KEEPQUOTES="
set "QUOTE="""
set "QUOTE=%QUOTE:~,1%"
set "QFLAG="
> "%OUTFILE%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
set "LINE=%%L"
call :SUB LINE
)
)
endlocal
exit /B
:SUB
setlocal EnableDelayedExpansion
set "LINE=!%1!"
set "LINENEW="
set /A "POS=0"
:LOOP
set "CHAR=!LINE:~%POS%,1!"
set /A "POS+=1"
if not defined CHAR (
echo(!LINENEW!
endlocal
exit /B
)
if "!CHAR!"=="!QUOTE!" (
if defined QFLAG (
set "QFLAG="
) else (
set "QFLAG=Quoted"
)
if defined KEEPQUOTES (
set "LINENEW=!LINENEW!!CHAR!"
)
) else if defined QFLAG (
if "!CHAR!"=="!SEARCH!" (
set "LINENEW=!LINENEW!!REPLACE!"
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
goto :LOOP

CMD script to find and replace a part of found line in file

I need to find all lines in myfile.txt containing word 'MyWord', and then replace a part of this string next way:
Original line:
...,31-01-2012,00,some_words_and_symbols_and_digits,MyWord,...
After replace:
...,31-01-2012,01,some_words_and_symbols_and_digits,MyWord,...
Please, help me to write this cmd script!
OK.. I have next code:
#echo off
set code=MyWord
set req=new request
FOR /F "usebackq delims=, tokens=1,2,3,4,5,6,7,8,9*" %%a in (MyFile.txt) do (
IF %%h==%code% (
SET tempstr=%%a,%%b,%%c,%%d,60,%%f,%%g,%%h,%%i
) ELSE (
SET tempstr=%%a,%%b,%%c,%%d,%%e,%%f,%%g,%%h,%%i
)
IF %%a==%req% (
SET echo %%a >> new.strings
) ELSE (
echo %tempstr% >> new.strings
)
)
#echo on
And I have in my file something like:
new request
...,31-01-2012,01,some_words_and_symbols_and_digits,MyWord,...
new request
...,30-11-2011,01,some_words_and_symbols_and_digits,OtherWords,...
But then I have error:
ELSE was unexpected at this time.
And If I'm trying simple next in the end
IF %%a==%req% SET tempstr=%%a
echo %tempstr% >> new.strings
Then I have only one last row instead of other else
You can use find command to filter the lines containing given text. As I see, the file is CSV. So you can use for /f to parse the lines found. Then you can echo all parsed files replacing the field you want.
This will replace all values in the 3rd column with "01"
#echo off
for /f "usebackq delims=, tokens=1,2,3,4,<put as many as you need>" %%A in (`find "MyWord" myfile.txt`) do echo %%A,%%B,01,%%D,<as many %%letters as tokens>
If you want to replace the value only on some lines, you can use if command inside for /f loop.
==== EDIT
The problem is with the value of req variable. It contains a space, so after substitution your second if statement has the following form:
IF %%a==new request (
so if %%a is equal to new it will execute request ( echo ...... ) and then ELSE is unexpected indeed. Enclose both %%a and %req% in quotation marks and the problem will disappear.
But I see also other problems. First, you have redundant set in your second if statement.
Second, you need to use delayed expansion of variables, or your echo %tempstr% won't work.
Your code after needed changes:
#Echo off
setlocal enabledelayedexpansion
set code=MyWord
set req=new request
FOR /F "usebackq delims=, tokens=1,2,3,4,5,6,7,8,9*" %%a in (MyFile.txt) do (
IF %%h==%code% (
SET tempstr=%%a,%%b,%%c,%%d,60,%%f,%%g,%%h,%%i
) ELSE (
SET tempstr=%%a,%%b,%%c,%%d,%%e,%%f,%%g,%%h,%%i
)
IF "%%a"=="%req%" (
echo %%a >> new.strings
) ELSE (
echo !tempstr! >> new.strings
)
)
endlocal

Resources