remove all double quotes in a file.txt - cmd

What I have to do is a batch script that:
_read a file line by line
_remove all the double quote characters writing the result in a file
My attempt was a script like:
for /f "usebackq tokens=*" %%a in ("%GRUPPI3%.txt") do (
SET VARIAB=%%a
SET RESULT=%VARIAB:"=%
echo %RESULT% >> output.txt
)
After some try I realized that the PROBLEM IS THE VARIABLE "VARIAB"!
Doing an echo of VARIAB the result is null or an old value (like an old line read by the variable %%a). (Why "VARIAB" doesn't become a copy of "%%a" as I would expect?)
I can't understand such a behaviour...
Someone know the solution?
Thanks
Cristian

#ECHO OFF
SETLOCAL
(
for /f "usebackq tokens=*" %%a in ("%GRUPPI3%.txt") do (
SET "VARIAB=%%a"
IF DEFINED variab (
SETLOCAL enabledelayedexpansion
SET "RESULT=!VARIAB:"=!"
ECHO(!RESULT!
ENDLOCAL
)
)
)>newfile.txt
GOTO :EOF
This should fix your problem. I changed the detination file to suit my system. If you want to append to the destination file, use >> in place of >

Related

Merge every 2nd line with previous line in batch scripting

I used the following code, but set Content is blank in my case. Please help. Thanks.
set content=
for /f "delims=" %%i in (fileA.txt) do set content=%%i
for /f "delims=" %%i in (FileA.txt) do set content=%content% %%i
ECHO %content%> result.txt
FileA.txt
test
A
Testing
B
Expected Output:
test A
Testing B
You need a single for command to process all lines and this simple logic: if it is the first line read, store it; else show the stored first line and the second one AND delete the first line, so the same logic be used in all line pairs:
#echo off
setlocal EnableDelayedExpansion
set "firstLine="
(for /F "delims=" %%a in (FileA.txt) do (
if not defined firstLine (
set "firstLine=%%a"
) else (
echo !firstLine! %%a
set "firstLine="
)
)) > result.txt
Your two for work independently (the second starts when the first is finished).
Your first loop gets the last line of the file and then the second adds every line of the textfile to the variable (there is a limit for variable length and you will soon reach it with this method).
The empty variable at the end is due to lack of using delayed expansion.
Work with a single for and an alternating flag instead:
#echo off
setlocal enabledelayedexpansion
set flag=0
(for /f "delims=" %%i in (FileA.txt) do (
if !flag!==0 (
<nul set /p ".=%%i "
) else (
echo %%i
)
set /a "flag=(flag+1) %% 2"
))>result.txt
Note: due to batch/cmd limitations, this may have some problems (line length, special characters
We need '#echo off' statement to not to print code on every execution of the program and only echo statements, 'rem' is to mention the line is a comment. 'SETLOCAL EnableExtensions EnableDelayedExpansion' is need to enable ! statements to resolve the variables.
#echo off
rem this for loop reads the file FileA.txt line by line by specifying delims= (nothing)
rem then checks the condition if the line is even line or not, if odd then adding it to myVar variable
rem if even then printing both earlier odd with the current even line to the result.txt file.
set myVar=
set nummod2=0
set /a i=0
rem creating an empty file on everytime the program runs
copy /y nul result.txt
SETLOCAL EnableExtensions EnableDelayedExpansion
for /f "delims=" %%a in (FileA.txt) do (
set /a i=i+1
set /a nummod2=i%%2
if !nummod2!==0 (
echo !myVar! %%a
) else (
set myVar=%%a
)
) >> result.txt;
echo 'Done with program execution. Result saved to result.txt in the same folder of this batchfile'
rem pause

Reading line by line from one file and write to another file using batch script

In below code i am tring to fetch the line no of string "AXX0000XXXA" from file data.txt,then fetching line by line and printing target.txt file,in between if the line reach the find line no i am adding one more line from file temp.txt.The code is working fine with the less nos of records(tested with 150 lines-File Size 100 kb),but when i am processing with 50K records(File Size 25MB) it is taking more then 25 minutes to process.could you please help me how i will process same in less time.
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set find_line=%%a)
set /a counter=0
for /f "usebackq delims=" %%b in (`"findstr /n ^^ C:\Users\23456\Desktop\data.txt"`) do (
set curr_line=%%b
set /a counter=!counter!+1
if !counter! equ !find_line! (
type temp.txt >> target.txt
)
call :print_line curr_line
)
endlocal
:print_line
setlocal enabledelayedexpansion
set line=!%1!
set line=!line:*:=!
echo !line!>>target.txt
endlocal
Your code uses three Batch file constructs that are inherently slow: call command, >> append redirection and setlocal/endlocal, and these constructs are executed once per each file line! It would be faster to include the subroutine into the original code to avoid the call and setlocal commands, and an echo !line!>>target.txt command imply open the file, search for the end, append the data and close the file, so it is faster to use this construct: (for ...) > target.txt that just open the file once. An example of a code with such changes is in Compo's answer.
This is another method to solve this problem that may run faster when the search line is placed towards the beginning of the file:
#echo off
setlocal enabledelayedexpansion
for /f "delims=:" %%a in ('findstr /n "AXX0000XXXA" "C:\Users\23456\Desktop\data.txt"') do (set /A find_line=%%a-1)
call :processFile < "C:\Users\23456\Desktop\data.txt" > target.txt
goto :EOF
:processFile
rem Duplicate the first %find_line%-1 lines
for /L %%i in (1,1,%find_line%) do (
set /P "line="
echo !line!
)
rem Insert the additional line
type temp.txt
rem Copy the rest of lines
findstr ^^
exit /B
This should create target.txt with content matching data.txt except for an inserted line taken from tmp.txt immediately above the line matching the search string, AXX0000XXXA.
#Echo Off
Set "fSrc=C:\Users\23456\Desktop\data.txt"
Set "iSrc=temp.txt"
Set "sStr=AXX0000XXXA"
Set "fDst=target.txt"
Set "iStr="
Set/P "iStr="<"%iSrc%" 2>Nul
If Not Defined iStr Exit/B
Set "nStr="
For /F "Delims=:" %%A In ('FindStr/N "%sStr%" "%fSrc%" 2^>Nul') Do Set "nStr=%%A"
If Not Defined nStr Exit/B
( For /F "Tokens=1*Delims=:" %%A In ('FindStr/N "^" "%fSrc%"') Do (
If "%%A"=="%nStr%" Echo %iStr%
Echo %%B))>"%fDst%"
I have made it easy for you to change your variable data, you only need to alter lines 3-6.
I have assumed that this was your intention, your question was not clear, please accept my apologies if I have assumed incorrectly.

to find a particular string alone using windows batch script

if my file conatins below text :
sampleA1xxx sampleA2yyyy sampleA3zzzzz ... sampleA4hhhhh
I want to find sampleA4 and display sampleA4hhhh using windows batch script.
Thats is my output should be: sampleA4hhhhh
Could anyone please help me.
take a batch or have a look at GNUWin sed:
>type file
^^sampleA1xxx ^^sampleA2yyyy ^^sampleA3zzzzz ^^sampleA4hhhhh
>sed -r "s/.*(\b\w+4\w+)/\1/" file
sampleA4hhhhh
#echo off
setlocal EnableDelayedExpansion
set target=sampleA4
set len=8
for /F "delims=" %%a in ('findstr "%target%" theFile.txt') do (
for %%b in (%%a) do (
set word=%%b
if "!word:~0,%len%!" equ "%target%" (
echo !word:~%len%!
)
)
)
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (q17316008.txt) DO SET line=%%i
SET line=%line:^= %
SET line=%line:*sampleA4=sampleA4%
FOR %%i IN (%line:^^= %) DO SET line=%%i&GOTO :done
:done
ECHO %line%
GOTO :EOF
This should do what I gather to be the task. It assumes that the "samplea4" string exists in the file's single line, is case-insensitive and the line doesn't exceed the ~8K limit on line length.
Simply replace the carets with spaces, lop off the leading characters to the first occurrence of the target string, and process that target string as a list; the first element will be the required string, so stop the processing when it's available.
OK, I tried this myself with a similar case and it worked fine:
for /f "tokens=4 delims=^^" %%a in (seperate.txt) do (echo %%a)
pause
Note: This is designed for a batch file, and replace the 4 after "tokens=" with whichever separated text you want to stop at.
Hope this helped,
Yours Mona.

Windows CMD FOR loop

I'm trying to make a code which will get first words from all lines of HELP's output to a variable and echo this variable. Here is my code:
#echo off
set a=
for /F "tokens=1,*" %%i in ('help') do (
set a=%a% %%i
)
echo %a%
But it returns first word from only last line. Why?
Bali C solved your problem as stated, but it looks to me like you are trying to get a list of commands found in HELP.
Some of the commands appear on multiple lines, so you get some extraneous words. Also there is a leading and trailing line beginning with "For" on an English machine that is not wanted.
Here is a short script for an English machine that will build a list of commands. The FINDSTR command will have to change for different languages.
#echo off
setlocal enableDelayedExpansion
set "cmds="
for /f "eol= delims=." %%A in ('help^|findstr /bv "For"') do (
for /f %%B in ("%%A") do set "cmds=!cmds! %%B"
)
set "cmds=%cmds:~1%"
echo %cmds%
EDIT
Ansgar Wiechers came up with a more efficient algorithm to extract just the command names at https://stackoverflow.com/a/12733642/1012053 that I believe should work with all languages. I've used his idea to simplify the code below.
#echo off
setlocal enableDelayedExpansion
set "cmds="
for /f %%A in ('help^|findstr /brc:"[A-Z][A-Z]* "') do set "cmds=!cmds! %%A"
set "cmds=%cmds:~1%"
echo %cmds%
You need to use delayed expansion in your for loop
#echo off
setlocal enabledelayedexpansion
set a=
for /F "tokens=1,*" %%i in ('help') do (
set a=!a! %%i
)
echo %a%
Instead of using %'s around the a variable, you use !'s to use delayed expansion.
Because the echo is outside the do ( ...... )
#echo off
for /F "tokens=1,*" %%i in ('help') do (
echo %%i
)
and no need to print a, you can use directly %%i.
Another very simple example could be a batch like this saved as help1.cmd
#echo off
for /F "tokens=1,*" %%i in ('help') do (
if /I "%%i" EQU "%1" echo %%j
)
and you call this batch like
help1 MKDIR
to get the short help text for the MKDIR command

Batch to remove duplicate rows from text file

Is it possible to remove duplicate rows from a text file? If yes, how?
Sure can, but like most text file processing with batch, it is not pretty, and it is not particularly fast.
This solution ignores case when looking for duplicates, and it sorts the lines. The name of the file is passed in as the 1st and only argument to the batch script.
#echo off
setlocal disableDelayedExpansion
set "file=%~1"
set "sorted=%file%.sorted"
set "deduped=%file%.deduped"
::Define a variable containing a linefeed character
set LF=^
::The 2 blank lines above are critical, do not remove
sort "%file%" >"%sorted%"
>"%deduped%" (
set "prev="
for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%sorted%") do (
set "ln=%%A"
setlocal enableDelayedExpansion
if /i "!ln!" neq "!prev!" (
endlocal
(echo %%A)
set "prev=%%A"
) else endlocal
)
)
>nul move /y "%deduped%" "%file%"
del "%sorted%"
This solution is case sensitive and it leaves the lines in the original order (except for duplicates of course). Again the name of the file is passed in as the 1st and only argument.
#echo off
setlocal disableDelayedExpansion
set "file=%~1"
set "line=%file%.line"
set "deduped=%file%.deduped"
::Define a variable containing a linefeed character
set LF=^
::The 2 blank lines above are critical, do not remove
>"%deduped%" (
for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%file%") do (
set "ln=%%A"
setlocal enableDelayedExpansion
>"%line%" (echo !ln:\=\\!)
>nul findstr /xlg:"%line%" "%deduped%" || (echo !ln!)
endlocal
)
)
>nul move /y "%deduped%" "%file%"
2>nul del "%line%"
EDIT
Both solutions above strip blank lines. I didn't think blank lines were worth preserving when talking about distinct values.
I've modified both solutions to disable the FOR /F "EOL" option so that all non-blank lines are preserved, regardless what the 1st character is. The modified code sets the EOL option to a linefeed character.
New solution 2016-04-13: JSORT.BAT
You can use my JSORT.BAT hybrid JScript/batch utility to efficiently sort and remove duplicate lines with a simple one liner (plus a MOVE to overwrite the original file with the final result). JSORT is pure script that runs natively on any Windows machine from XP onward.
#jsort file.txt /u >file.txt.new
#move /y file.txt.new file.txt >nul
you may use uniq http://en.wikipedia.org/wiki/Uniq from UnxUtils http://sourceforge.net/projects/unxutils/
Some time ago I found an unexpectly simple solution, but this unfortunately only works on Windows 10: the sort command features some undocumented options that can be adopted:
/UNIQ[UE] to output only unique lines;
/C[ASE_SENSITIVE] to sort case-sensitively;
So use the following line of code to remove duplicate lines (remove /C to do that in a case-insensitive manner):
sort /C /UNIQUE "incoming.txt" /O "outgoing.txt"
This removes duplicate lines from the text in incoming.txt and provides the result in outgoing.txt. Regard that the original order is of course not going to be preserved (because, well, this is the main purpose of sort).
However, you sould use these options with care as there might be some (un)known issues with them, because there is possibly a good reason for them not to be documented (so far).
The Batch file below do what you want:
#echo off
setlocal EnableDelayedExpansion
set "prevLine="
for /F "delims=" %%a in (theFile.txt) do (
if "%%a" neq "!prevLine!" (
echo %%a
set "prevLine=%%a"
)
)
If you need a more efficient method, try this Batch-JScript hybrid script that is developed as a filter, that is, similar to Unix uniq program. Save it with .bat extension, like uniq.bat:
#if (#CodeSection == #Batch) #then
#CScript //nologo //E:JScript "%~F0" & goto :EOF
#end
var line, prevLine = "";
while ( ! WScript.Stdin.AtEndOfStream ) {
line = WScript.Stdin.ReadLine();
if ( line != prevLine ) {
WScript.Stdout.WriteLine(line);
prevLine = line;
}
}
Both programs were copied from this post.
set "file=%CD%\%1"
sort "%file%">"%file%.sorted"
del /q "%file%"
FOR /F "tokens=*" %%A IN (%file%.sorted) DO (
SETLOCAL EnableDelayedExpansion
if not [%%A]==[!LN!] (
set "ln=%%A"
echo %%A>>"%file%"
)
)
ENDLOCAL
del /q "%file%.sorted"
This should work exactly the same. That dbenham example seemed way too hardcore for me, so, tested my own solution. usage ex.: filedup.cmd filename.ext
Pure batch - 3 effective lines.
#ECHO OFF
SETLOCAL
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
FOR /f "delims=" %%a IN (q34223624.txt) DO SET $%%a=Y
(FOR /F "delims=$=" %%a In ('set $ 2^>Nul') DO ECHO %%a)>u:\resultfile.txt
GOTO :EOF
Works happily if the data does not contain characters to which batch has a sensitivity.
"q34223624.txt" because question 34223624 contained this data
1.1.1.1
1.1.1.1
1.1.1.1
1.2.1.2
1.2.1.2
1.2.1.2
1.3.1.3
1.3.1.3
1.3.1.3
on which it works perfectly.
Did come across this issue and had to resolve it myself because the use was particulate to my need.
I needed to find duplicate URL's and order of lines was relevant so it needed to be preserved. The lines of text should not contain any double quotes, should not be very long and sorting cannot be used.
Thus I did this:
setlocal enabledelayedexpansion
type nul>unique.txt
for /F "tokens=*" %%i in (list.txt) do (
find "%%i" unique.txt 1>nul
if !errorlevel! NEQ 0 (
echo %%i>>unique.txt
)
)
Auxiliary: if the text does contain double quotes then the FIND needs to use a filtered set variable as described in this post: Escape double quotes in parameter
So instead of:
find "%%i" unique.txt 1>nul
it would be more like:
set test=%%i
set test=!test:"=""!
find "!test!" unique.txt 1>nul
Thus find will look like find """what""" file and %%i will be unchanged.
I have used a fake "array" to accomplish this
#echo off
:: filter out all duplicate ip addresses
REM you file would take place of %1
set file=%1%
if [%1]==[] goto :EOF
setlocal EnableDelayedExpansion
set size=0
set cond=false
set max=0
for /F %%a IN ('type %file%') do (
if [!size!]==[0] (
set cond=true
set /a size="size+1"
set arr[!size!]=%%a
) ELSE (
call :inner
if [!cond!]==[true] (
set /a size="size+1"
set arr[!size!]=%%a&& ECHO > NUL
)
)
)
break> %file%
:: destroys old output
for /L %%b in (1,1,!size!) do echo !arr[%%b]!>> %file%
endlocal
goto :eof
:inner
for /L %%b in (1,1,!size!) do (
if "%%a" neq "!arr[%%b]!" (set cond=true) ELSE (set cond=false&&goto :break)
)
:break
the use of the label for the inner loop is something specific to cmd.exe and is the only way I have been successful nesting for loops within each other. Basically this compares each new value that is being passed as a delimiter and if there is no match then the program will add the value into memory. When it is done it will destroy the target files contents and replace them with the unique strings

Resources