Batch encoding text files - windows

I have this code to read a text file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /f "delims=" %%x in ('type text.txt') do (
set "Var=%%x"
ECHO !Var!
)
pause
My question is that if i could advance every char in the file by 20 places like "a" would be "t". it can have numbers and symbols too. the txt file is 400 line long and there is between 1 and 120 char per line. does any one know how i could do this.

Sorry, this will not handle all the posibilities, but
#echo off
setlocal enableextensions disabledelayedexpansion
call :setTables
set "inputFile=inputFile.txt"
for /f "usebackq delims=*" %%a in ("%inputFile%") do (
set "data=%%a"
call :handleProblems
set "out="
setlocal enabledelayedexpansion
for /f "delims=" %%b in ('cmd /v:off /q /u /c "echo(!data!"^|more') do (
if defined "%%b" (
set "out=!out!!"%%b"!"
) else (
set "out=!out!%%b"
)
)
echo(!out!
endlocal
)
exit /b
:handleProblems
set "data=%data:!=~%"
set "data=%data:<=^<%"
set "data=%data:>=^>%"
set "data=%data:&=^&%"
set "data=%data:|=^|%"
set "data=%data:)=^)%"
exit /b
:setTables
set ""a"=t"
set ""b"=u"
set ""c"=v"
set ""d"=w"
set ""e"=x"
set ""f"=y"
set ""g"=z"
set ""h"=a"
set ""i"=b"
set ""j"=c"
set ""k"=d"
set ""l"=e"
set ""m"=f"
set ""n"=g"
set ""o"=h"
set ""p"=i"
set ""q"=j"
set ""r"=k"
set ""s"=l"
set ""t"=m"
set ""u"=n"
set ""v"=o"
set ""w"=p"
set ""x"=q"
set ""y"=r"
set ""z"=s"
set ""~"=!"
set ""^&"=&"
exit /b

Use GnuSed and the "y/abc/tuv/" transliteration command which would replace a with t, b with u and c with v
This syntax works - just extend the character sets:
sed "y/abc/tuv/" "file.txt" >"newfile.txt"

Related

Count the underscores in the Filename with a bat

I have searched this everywhere and I didn't found it, so what I want to do is simple, I want to count the underscores in a filename and put it in a variable to later use it.
Is there any simple batch code to do it ?
#echo off
setlocal enabledelayedexpansion
set filename=__example_file.bin_
set cnt=0
set pos=0
:loop
if "!filename:~%pos%,1!"=="_" set /a cnt=%cnt%+1
set /a pos=%pos%+1
if not "!filename:~%pos%,1!"=="" goto loop
echo Count: %cnt%
That code is pretty ugly but I can't find a better way so far.
A different method to count underscores (or more exact elements separated by an underscore)
is to use self expanding code:
:: Q:\Test\2017\08\28\SO_45917406.cmd
#echo off & setlocal enabledelayedexpansion
set "FileName=example_file_name_20170828_181000.txt"
Set i=1&Set "FileName[!i!]=%FileName:_="&Set /a i+=1&Set "FileName[!i!]=%"
Echo Counted %i% underscore separated elements
Set FileName
Sample output:
> Q:\Test\2017\08\28\SO_45917406.cmd
Counted 5 underscore separated elements
FileName=example_file_name_20170828_181000.txt
FileName[1]=example
FileName[2]=file
FileName[3]=name
FileName[4]=20170828
FileName[5]=181000.txt
This solution is inspired from #xmcp :
#echo off
Rem The srting to count in the filename is the underscrore "_"
Rem we can of course set another one ;)
set "MyString=_"
setlocal enabledelayedexpansion
#for /f "delims=" %%a in ('Dir /b "%userprofile%\Desktop"') do (
set "filename=%%a"
set /a "cnt=0"
set /a "pos=0"
Call:Counting_String "!filename!" "%Mystring%"
)
pause & exit
::*********************************************************
:Counting_String <filename> <MyString>
set "filename=%~1"
set "string=%~2"
if /I "!filename:~%pos%,1!"=="%Mystring%" set /a cnt+=1
set /a pos+=1
if not "!filename:~%pos%,1!"=="" goto Counting_String
echo !filename!: [!cnt!] "%Mystring%"
exit /b
::*********************************************************

How to sort file names numerically in windows command line?

The windows explorer does display in correct order. For example: filename1.txt, filename2.txt, filename11.txt etc. When I tried the DIR command with different options could not get the same behaviour. It displays filename1.txt, filename11.txt, filename2.txt.
Is there any way to sort it so that numeric ordering is preserved?
#ECHO Off
:: dir list in numeric-value order
SETLOCAL
:: %1= directoryname; default current directory
SET "targetdir=%~1"
IF NOT DEFINED targetdir SET "targetdir=.\*.*"
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
SET /a maxnumlength=0
SET "manyzeroes=0000000000000000"
SET "manyzeroes=%manyzeroes%%manyzeroes%%manyzeroes%%manyzeroes%"
:: analyse list of filenames
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%" '
) DO CALL :detnlen "%%a"
:: build list of filenames
FOR /f "delims=" %%a IN (
'dir /b /a-d "%targetdir%" '
) DO CALL :setname "%%a"
FOR /F "tokens=1*delims=:" %%a In ('set $ 2^>Nul') DO ECHO %%b
GOTO :EOF
:detnlen
SET "name=%~1"
SET /a numlength=0
SET "action=L"
:detnloop
IF %action%==F SET "action=B"
SET "post=%name:~0,1%"&SET "name=%name:~1%"
IF "%post%" geq "0" IF "%post%" leq "9" (
SET /a numlength+=1
SET "action=F"
)
IF %action% neq B IF DEFINED name GOTO detnloop
IF %numlength% gtr %maxnumlength% SET /a maxnumlength=%numlength%
GOTO :EOF
:setname
SET "name=%~1"
SET "pre="
SET "nums="
SET "action=L"
:snloop
IF %action%==F SET "action=B"
SET "post=%name:~0,1%"&SET "name=%name:~1%"
IF "%post%" geq "0" IF "%post%" leq "9" (
SET /a numlength+=1
SET "action=F"
SET "nums=%nums%%post%"
)
IF %action%==L SET "pre=%pre%%post%"&SET "post="
IF %action% neq B IF DEFINED name GOTO snloop ELSE SET "post="
IF %action%==F SET "post="
IF DEFINED nums SET "nums=%manyzeroes%%nums%"
IF DEFINED nums CALL SET "nums=%%nums:~-%maxnumlength%%%"
SET "$%pre%%nums%%post%%name%=:%~1"
GOTO :EOF
Oh, my!
There are no inbuilt switches to show the directory in that odd way, but this has all the hallmarks of a challenge.
OK - it's insanely slow, but it appears to work.
The principle is to determine the longest sequence of initial-numerics as maxnumlength then assign the name of the detected file to an environment variable starting $ and with a name constructed from the filename with the numeric part leading-zero-padded. set $ then lists the $ variables in alphabetic order; select the value, which is the original filename.

Windows Batch File can't use variable in for syntax

I want to use a variable skip parameter in for loop, but it won't let me do it.
Here is my code
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
for /f "%skip%" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
)
Here skip is skip=1, but it doesn't skip any line. When I replace it with skip=1. then it works fine, but I want to skip variable no. of lines in each iteration. Please help.
I think with this logic the only option is a subroutine:
#echo off
setlocal ENABLEDELAYEDEXPANSION
set /p testcase=<testcases.txt
set /a end=%testcase%*13
for /L %%P IN (1,13,%end%) DO (
set skip=skip=%%P
echo !skip!
set vidx=0
call :innerFor %%P
)
exit /b 0
:innerFor
for /f "skip=%~1" %%A in (testcases.txt) do (
set /a vidx=!vidx! + 1
set var!vidx!=%%A
)
exit /b 0
parametrization of FOR /F options is a little bit tricky..
Though I have no the content of your files I cant test if this works correctly .

Windows Batch: Split String to individual characters to variables

in Windows Batch, if I had a variable (length can change) that was, for example: "hello world!"
is it possible to "split" the variable so each character is its own variable so the output could look like:
t1=h
t2=e
t3=l
etc.
Any help would be appreciated.
Use this code:
setlocal EnableDelayedExpansion
set str="hello world^!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=%count%-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
To get the nth character in a string, use set char=%str:~n,1%.
I hope this was helpful!
Here is a variant using for /L to iterate over all characters of the string. The number of characters, so the length of the string, is retrieved in sub-routine :LENGTH first:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
call :LENGTH LEN "%_STRING%"
setlocal EnableDelayedExpansion
for /L %%I in (0,1,%LEN%) do (
set "$CHR[%%I]=!_STRING:~%%I,1!"
)
set $CHR
endlocal
endlocal
exit /B
:LENGTH rtn_length val_string
setlocal DisableDelayedExpansion
set /A "RET=0" & set "STR=%~2"
if defined STR set /A "RET=1"
setlocal EnableDelayedExpansion
for %%L in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!STR:~%%L,1!"=="" (
set /A "RET+=%%L"
set "STR=!STR:~%%L!"
)
)
(
endlocal
endlocal
set "%~1=%RET%"
)
exit /B
Here is a different variant, using cmd /U to convert the string into Unicode, where a null-byte becomers inserted behind every character, and find, which treats these null-bytes like end-of-line markers:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
set /A "IDX=0"
for /F delims^=^ eol^= %%I in ('
cmd /U /V /C echo^(!_STRING!^| find /V ""
') do (
set "CHR=%%I"
setlocal EnableDelayedExpansion
for /F "delims=" %%J in ("$CHR[!IDX!]=!CHR!") do (
endlocal
set "%%J"
)
set /A "IDX+=1"
)
set $CHR
endlocal
exit /B
Finally, here is another variant, based on a goto loop. This uses a position pointer POS to scan the string and to extract a single character. If no character is returned, the end of the string is reached:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_STRING=Hello world!"
setlocal EnableDelayedExpansion
if not defined _STRING goto :QUIT
set /A "POS=0"
:LOOP
set "CHR=!_STRING:~%POS%,1!"
if defined CHR (
set "$CHR[%POS%]=!CHR!"
set /A "POS+=1"
goto :LOOP
)
:QUIT
set $CHR
endlocal
endlocal
exit /B
Old thread, but accepted answer misses letter d?
Changed
set /a pos=%count%-1 to
set /a pos=!count!-1
setlocal EnableDelayedExpansion
set str="hello world!"
set tempstr=%str%
set count=0
:loop
if defined tempstr (
set tempstr=%tempstr:~1%
set /a count+=1
set /a pos=!count!-1
set t!count!=!str:~%pos%,1!
goto loop
)
:: check the generated variables
set t
pause
Here is another version.
variables start with 0, though
setlocal EnableDelayedExpansion
set var="hello world!"
rem remove quotes
set var=%var:"=%
rem add limiter
set var=%var%_
echo %var%
set count=0
:loop
set tempvar=!var:~%count%,1!
if !tempvar!==_ goto skip
set arr!count!=!tempvar!
set /a count=!count!+1
goto loop
:skip
echo out
echo display output
set arr
pause

Reading from a csv file and extracting certain data columns based on first column value

This is my first batch program and I have been searching online but still struggling to write up a solution.
I have the following CSV file:
"RH",2013/06/15 02:14:58 -0400,"X","LQ3SUEEWPWKL6",005,
"FH",01
"SH",2013/06/14 00:00:00 -0400,2013/06/14 23:59:59 -0400,"LQ3SUEEWPWKL6",""
"CH","TransactionID","InvoiceID",
......
I'm trying to write a simple program to do the following:
If column1 = "RH", then extract column2 value (2013/06/15 02:14:58 -0400)
If column1 = "SH", then extract column4 value (LQ3SUEEWPWKL6)
and pipe output to a file.
This is my code so far but the if condition is not working for me
#echo off
:: Set input file in variable
::Set _InputFile=%1
:: Store input line into different variables
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
Set _var1=%%A
Set _var2=%%B
Set _var3=%%C
Set _var4=%%D
Set _var5=%%E
Set _var6=%%F
Set _var7=%%G
Set _var8=%%H
Set _var9=%%I
Set _var10=%%J
Set _var11=%%K
Set _var12=%%L
Set _var13=%%M
Set _var14=%%N
Set _var15=%%O
Set _var16=%%P
Set _var17=%%Q
Set _var18=%%R
IF "%_var1%"=="RH" echo %var2%
)
My CSV file looks fine in Excel and Notepad but when I execute the script to display the first variable, it looks like there's some garbage characters just before the "RH" on the first record - I cannot bypass it since I need to extract additional column data if var1 = "RH":
"RH"
FH
01
SH
CH
TransactionID,PaymentTrackingID,
SF
SF
SC
RF
CAD,CR,0
RF
USD,CR,0
RC
FF
(
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
if "%%~A"=="RH" echo %%~B
if "%%~A"=="SH" echo %%~D
)
)>youroutputfilename
Should work - no need to assign all the values to different variables - BUT if you plan to use them, then
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
...
Set _var17=%%Q
Set _var18=%%R
CALL :PROCESS
)
...
GOTO :EOF
:PROCESS
IF %_var1%=="RH" echo %_var2%
IF %_var1%=="SH" echo %_var4%
GOTO :EOF
Note that with this method, since you are assigning %%x to _varx then if %%x is quoted, the quotes will be INCLUDED in the value assigned. To remove the enclosing quotes (if they exist) use SET _varx=%%~x.
Addendum 20130703-1956Z for OP's problem
#ECHO OFF
SETLOCAL
SET _Inputfile=u:\noname1.txt
(
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
SET "RH="
SET "SH="
ECHO(%%A|FINDSTR /l /c:"\"RH\"" >NUL
IF NOT ERRORLEVEL 1 SET RH=Y
ECHO(%%A|FINDSTR /l /c:"\"SH\"" >NUL
IF NOT ERRORLEVEL 1 SET SH=Y
if DEFINED RH echo %%~B
if DEFINED SH echo %%~D
)
)>u:\youroutputfilename
TYPE u:\youroutputfilename
del u:\youroutputfilename
echo========First way
(
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
SET _var1=%%A
SET "RH="
SET "SH="
CALL :process
if DEFINED RH echo %%~B
if DEFINED SH echo %%~D
)
)>u:\youroutputfilename
TYPE u:\youroutputfilename
del u:\youroutputfilename
echo========Second way
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
SET _var1=%%A
IF "!_var1:~-4!"==""RH"" echo %%~B
IF "!_var1:~-4!"==""SH"" echo %%~D
)
)>u:\youroutputfilename
TYPE u:\youroutputfilename
del u:\youroutputfilename
echo========Third way
ENDLOCAL
GOTO :EOF
:process
IF "%_var1:~-4%"==""RH"" SET RH=Y
IF "%_var1:~-4%"==""SH"" SET SH=Y
GOTO :EOF
You have a parsing issue. First end the for loop with ), after this you can use the new variables:
#echo off
:: Set input file in variable
::Set _InputFile=%1
:: Store input line into different variables
FOR /F "tokens=1-18* delims=," %%A IN (%_InputFile%) DO (
Set "_var1=%%A"
Set "_var2=%%B"
Set "_var3=%%C"
Set "_var4=%%D"
Set "_var5=%%E"
Set "_var6=%%F"
Set "_var7=%%G"
Set "_var8=%%H"
Set "_var9=%%I"
Set "_var10=%%J"
Set "_var11=%%K"
Set "_var12=%%L"
Set "_var13=%%M"
Set "_var14=%%N"
Set "_var15=%%O"
Set "_var16=%%P"
Set "_var17=%%Q"
Set "_var18=%%R"
)
IF "%_var1%"=="RH" echo %var2%
You need to enable delayed expansion:
#echo off
setlocal EnableDelayedExpansion
set "_InputFile=..."
for /f "tokens=1-18* delims=," %%A in (%_InputFile%) do (
Set _var1=%%A
Set _var2=%%B
...
if "!_var1!"=="RH" echo !_var2!
)
as there was no answer to the "why does my line starts with "RH"", I'll do some gravedigging.
So, the  comes from the BOM (Byte Order Mark) which indicates the file is in UTF, and the way the bytes are written if necessary.
for the answer:
you can use
if x%_var1:RH=%x NEQ x%_var1%x (echo %_var2%)
this will check if RH is in %_var1% (if after replacing RH in the var, it is unchanged, RH is not in the var)
which means, whether the Bom is here or not is not important. Though, you'll have problems if you want an exact match.
another way to deal with it is to not include the bom in your file, which means saving either in ASCII or UTF-8 without BOM; Or using a tool to strip the bom from your UTF-8 file.

Resources