Page 1 of 2

Return character of specific position in a line

Posted: 11 Jun 2013 12:33
by CMOS
Is it possible, using a batch file, to determine what character is in a certain position of a line in a text file?

So if I have a text file and I want to check what character is in position 10 and perform a correlating function based on the result of the line, how can I do that?

There are several possible variations of what could in that position, I believe around 10. It's only one character in length as well, so I couldn't find a way to make it work with Findstr. Output would need to match the original formatting as well.

Any help would be appreciated.

Thank you.

Re: Return character of specific position in a line

Posted: 11 Jun 2013 14:45
by aGerman
There are several possibilities.

Try

Code: Select all

@echo off &setlocal
call :getchar "test.txt" 2 5 char
if errorlevel 1 echo ERROR!
echo %char%
pause
goto :eof

:getchar  fname_in  line_in  position_in  char_out
set "%~4="
setlocal EnableExtensions DisableDelayedExpansion
set "file=%~1"
set /a "line=%~2, pos=%~3 - 1"
for /f %%i in ('type "%file%"^|find /c /v ""') do set /a "max=%%i"
if %line% gtr %max% (endlocal &exit /b 1)
<"%file%" (for /l %%i in (1 1 %line%) do (set "txt=" &set /p "txt="))
setlocal EnableDelayedExpansion
if "!txt!"=="" (endlocal &endlocal &exit /b 1)
set "char=!txt:~%pos%,1!"
if "!char!"=="" (endlocal &endlocal &exit /b 1)
endlocal &endlocal &set "%~4=%char%" &exit /b 0


The function assigns the 5th character of line 2 in test.txt to the variable char.

Regards
aGerman

EDIT pos=%~3 + 1 TO pos=%~3 - 1

Re: Return character of specific position in a line

Posted: 11 Jun 2013 14:52
by Aacini
Your question is too vague. You may directly extract the character at position 10 via Batch substring extraction:

Code: Select all

set line=ABCDEFGHIJKLMN
set charAt10=%line:~9,1%

About correlating one value to another one, my favorite method is via an array:

Code: Select all

set relate[A]=Value related to A
set relate[B]=Value related to B
. . .
set relate[J]=Value related to J

echo The value related to %charAt10% is !relate[%charAt10%]!

Perhaps if you explain more clearly your problem we may help you in a better way...

Antonio

Re: Return character of specific position in a line

Posted: 11 Jun 2013 17:22
by CMOS
Sorry for the ambiguity, I'll try and explain better.

I have text files (and receive more daily) that contain a varying number of lines, some nights it could be 400, others 387, others 245, etc... Each line contains 1000 characters and is formatted in a specific fashion. The 10th character of each line determines how I use the information contained in that line. So what I'd like to do is search each line of the file, determine the 10th character of the line and then if it matches the desired character (say A), take that entire line of information out of the text file and put it into a second text file in the same format.

Hopefully I did a better job explaining. I appreciate the assistance so far!

Re: Return character of specific position in a line

Posted: 11 Jun 2013 17:43
by aGerman
Something like that should work:

Code: Select all

@echo off &setlocal

set "infile=in.txt"
set "outfile=out.txt"
set "char=A"
set "pos=10"

setlocal EnableDelayedExpansion
set /a "pos -= 1"
<"!infile!" >"!outfile!" (
  for /f %%i in ('type "!infile!"^|find /c /v ""') do for /l %%j in (1 1 %%i) do (
    set "line=" &set /p "line="
    if defined line if "!line:~%pos%,1!"=="!char!" echo(!line!
  )
)

Regards
aGerman

Re: Return character of specific position in a line

Posted: 11 Jun 2013 19:14
by Aacini

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem I have text files (and receive more daily) that contain a varying number of lines
(for %%a in (*.txt) do (

   rem Each line contains 1000 characters
   rem I'd like to do is search each line of the file,
   for /F "usebackq delims=" %%b in ("%%a") do (
     
      rem if the 10th character of the line matches the desired character (say A)
      set "line=%%b"
      if "!line:~9,1!" equ "A" (

         rem take that entire line of information out of the text file
         echo !line!

      )
   )

rem and put it into a second text file in the same format.
)) > secondFile.txt


I hope it helps!

Antonio

Re: Return character of specific position in a line

Posted: 12 Jun 2013 10:11
by CMOS
Aacini wrote:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem I have text files (and receive more daily) that contain a varying number of lines
(for %%a in (*.txt) do (

   rem Each line contains 1000 characters
   rem I'd like to do is search each line of the file,
   for /F "usebackq delims=" %%b in ("%%a") do (
     
      rem if the 10th character of the line matches the desired character (say A)
      set "line=%%b"
      if "!line:~9,1!" equ "A" (

         rem take that entire line of information out of the text file
         echo !line!

      )
   )

rem and put it into a second text file in the same format.
)) > secondFile.txt


I hope it helps!

Antonio


Thank you both for the assistance. The quoted code worked great save one issue I'm having... as mentioned the value of the 10th character determines how the line is used. So I added more IF statements to match the characters (A through E). This part seems to work fine as any lines matching that indicator get moved into the desired text file. However, all the lines that don't match need to get moved to a different text file as well. I didn't think I had to have all the comparisons again (ie. line ~9,1 NEQ "A") but an added else statement is not providing the desired results.

What am I missing?

Thanks again.

Re: Return character of specific position in a line

Posted: 12 Jun 2013 10:58
by Squashman
How about posting your revised code?

Re: Return character of specific position in a line

Posted: 12 Jun 2013 14:06
by CMOS
Squashman wrote:How about posting your revised code?


Sure...

Code: Select all

@echo off
setlocal EnableDelayedExpansion

(for %%a in (*.txt) do (

     for /F "usebackq delims=" %%b in ("%%a") do (
     
      set "line=%%b"
      if "!line:~9,1!" equ "A" (
         echo !line!
      )
      if "!line:~9,1!" equ "B" (
         echo !line!
      )
      if "!line:~9,1!" equ "C" (
         echo !line!
      )
     if "!line:~9,1!" equ "D" (
         echo !line!
      )
     if "!line:~9,1!" equ "E" (
         echo !line!
      )

   )
)) > secondFile.txt


This seems to work; if the 10th character matches any of those letters it echos the contents of that line to a textfile. Because batch files don't support OR (at least I couldn't find any syntax or example of it), I'm not sure how to write my IF statement so the code iterates through each if statement and then if the 10th character doesn't match that code to the redirect that output to a different textfile. Ideally, it would be If (in relative psuedo code) x equ "A" or "B" or "C" etc.. echo line to file A else echo line to file B.

Thanks in advance.

Re: Return character of specific position in a line

Posted: 12 Jun 2013 14:32
by Acy Forsythe
Try this if you want to separate the files. Using nested IF/ELSE can get a little convoluted, so I'd stick to the multiple IF statements until you feel more comfortable...

Code: Select all

@echo off
setlocal EnableDelayedExpansion

(for %%a in (*.txt) do (

     for /F "usebackq delims=" %%b in ("%%a") do (
     
      set "line=%%b"
      if "!line:~9,1!" equ "A" (
         echo !line!
    Set "FileName=FileA"
      )
      if "!line:~9,1!" equ "B" (
         echo !line!
    Set "FileName=FileB"
      )
      if "!line:~9,1!" equ "C" (
         echo !line!
    Set "FileName=FileC"
      )
     if "!line:~9,1!" equ "D" (
         echo !line!
         Set "FileName=FileD"
      )
     if "!line:~9,1!" equ "E" (
         echo !line!
         Set "FileName=FileE"
      )

   )
)) > %FileName%.txt

Re: Return character of specific position in a line

Posted: 12 Jun 2013 14:48
by Aacini
It is a very bad practice to develop a program in "little steps" (when requirement A is fulfilled, request requirement B; when it is fulfilled request the C and so on) because is frequent that a posterior modification entirely replaces a previous one, so our efforts in the development of such modifications is wasted. The best programs are developed fulfilling complete requirements.

The Batch file below check if the 10th character is anyone of A through E and send the line to secondFile.txt if the answer is true, otherwise the line is sent to differentFile.txt:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set matchingChars=ABCDE
del secondFile.txt 2> NUL
del differentFile.txt 2> NUL

rem I have text files (and receive more daily) that contain a varying number of lines
for %%a in (*.txt) do (

   rem Each line contains 1000 characters
   rem I'd like to do is search each line of the file,
   for /F "usebackq delims=" %%b in ("%%a") do (
     
      rem if the 10th character of the line is anyone of matchingChars
      set "line=%%b"
      for %%c in ("!line:~9,1!") do set "matchedChars=!matchingChars:%%~c=!"
      if "!matchedChars!" neq "%matchingChars%" (

         rem take that entire line of information out of the text file
         rem and put it into a second text file in the same format.
         echo !line!>> secondFile.txt

      ) else (

         rem the lines that don't match need to get moved to a different text file
         echo !line!>> differentFile.txt

      )
   )

)


Antonio

Re: Return character of specific position in a line

Posted: 18 Jun 2013 09:08
by CMOS
Aacini wrote:It is a very bad practice to develop a program in "little steps" (when requirement A is fulfilled, request requirement B; when it is fulfilled request the C and so on) because is frequent that a posterior modification entirely replaces a previous one, so our efforts in the development of such modifications is wasted. The best programs are developed fulfilling complete requirements.

The Batch file below check if the 10th character is anyone of A through E and send the line to secondFile.txt if the answer is true, otherwise the line is sent to differentFile.txt:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set matchingChars=ABCDE
del secondFile.txt 2> NUL
del differentFile.txt 2> NUL

rem I have text files (and receive more daily) that contain a varying number of lines
for %%a in (*.txt) do (

   rem Each line contains 1000 characters
   rem I'd like to do is search each line of the file,
   for /F "usebackq delims=" %%b in ("%%a") do (
     
      rem if the 10th character of the line is anyone of matchingChars
      set "line=%%b"
      for %%c in ("!line:~9,1!") do set "matchedChars=!matchingChars:%%~c=!"
      if "!matchedChars!" neq "%matchingChars%" (

         rem take that entire line of information out of the text file
         rem and put it into a second text file in the same format.
         echo !line!>> secondFile.txt

      ) else (

         rem the lines that don't match need to get moved to a different text file
         echo !line!>> differentFile.txt

      )
   )

)


Antonio


I wanted to follow up on this and say thank you for the help. The provided code above worked great.

Can someone explain, or share a link that explains, the difference between %variable% and !variable! ?

Thanks again.

Re: Return character of specific position in a line

Posted: 18 Jun 2013 22:01
by foxidrive
CMOS wrote:Can someone explain, or share a link that explains, the difference between %variable% and !variable! ?


The !variable! is used when delayed expansion is in effect

Google on setlocal and enabledelayedexpansion

Re: Return character of specific position in a line

Posted: 19 Jun 2013 06:39
by Squashman

Re: Return character of specific position in a line

Posted: 20 Jun 2013 13:45
by CMOS
Thank you for the links... I believe I'm starting to get it.

With that said, I'm curious if given the same information given above if there's a way to extract the previous and subsequent line after finding a matching character? It's not entirely necessary but I'm interesting in if there are methods to cycle through the data within the loop?

Thank you.