0

I have a batch file that asks the user for 2 inputs. A text file is then created/updated which includes the entries the user has entered. These entries need to be of a specific format.

i.e. (FIRST INPUT) letter, letter, number number,space,number,letter,number,number,number, space letter,letter.

e.g. AB52 7L056 TA (all letters need to be in upper case)

(SECOND INPUT) Letter,letter,letter,number,letter,space,(then 11 numbers).

e.g. EBH9E 12323405432

I also need to limit the input so there is no space entered at the end of each input. My code so far is:

@echo off
@echo This is a test :> dblank.txt
SET /P someVar=[Please enter STRING and press ENTER]
@echo [THIS IS THE STRING ENTERED] %someVar% >> dblank.txt
@echo This is another TEST :>> dblank.txt
SET /P someVar2=[Please enter NEXT STRING and press ENTER]
@echo [THIS IS THE SECOND STRING ENTERED] %someVar2% >> dblank.txt
@echo DOES IT WORK ???>> dblank.txt

Could someone help with this? Many thanks in advance.

  • What you need is [Findstr](https://technet.microsoft.com/en-us/library/bb490907.aspx) => ***Searches for patterns of text in files using regular expressions.*** Then... when you now how it works... use it like [this example](http://stackoverflow.com/questions/21901077/findstr-does-not-work-with-set-p) – gmo Mar 30 '15 at 07:45
  • Had a look at FINDSTR and it seems to search for strings in files ? I need to force the user running the batch file to enter the string in the correct format. The entered string is then saved in the txt file that is created by the batch file. – andrew davies Mar 30 '15 at 09:36
  • I still recommend the use of `Findstr` because you need a ´regex´ match.. Try saving that file with a temp name, do the check and if it's ok.. rename and continue, if not, warn the user and remove the temporary file. – gmo Mar 30 '15 at 10:04
  • More with var examples as you need: http://stackoverflow.com/a/15730788/1601332 And a Must read for this function: http://stackoverflow.com/questions/8844868/what-are-the-undocumented-features-and-limitations-of-the-windows-findstr-comman – gmo Mar 30 '15 at 10:11

2 Answers2

0

Well, it is very different to read any input from the user and then validate it (and repeat the process until the user enter the right input), than limit the input to a given format, so invalid characters are just not accepted. For the first method you may use findstr command as previously suggested.

Some time ago I wrote a Batch program that achieves precisely this type of formatted input. This is its help screen:

Read a line from keyboard with specific format

call :ReadFormattedLine var="mask"  [/M "message"]  [/P]  [/A|/W|/F]

The mask specify valid input characters per position via the following chars:

   #  -  Any digit
   _  -  Any letter
   +  -  A letter that is converted to uppercase
   ?  -  Any letter or digit
   @  -  Letter or digit, convert letter to uppercase

The following characters are just displayed/inserted at their positions:
   $  /  \  (  )  [  ]  :  ;  ,  .  -  space  letters  digits

Any character in the mask different than previous ones cause an error.

If /P (password) switch is given, input characters are displayed as asterisks.

Normally the input is completed when Enter key is pressed after read at least
one character, but the following switches changes this behavior.

   /A (auto):   Input is auto-completed after the last character; Enter key
                is ignored.
   /W (whole):  Enter key is accepted at first or last input positions only,
                that is, when input is empty or whole.
   /F (fields): Enter key fills the field with spaces and move the cursor to
                the next input field in the line.

To input a whole value terminated by Enter, use /W switch and insert any
character at the first position in the mask.

Using :ReadFormattedLine subroutine you may solve your problem this way:

call :ReadFormattedLine FirstInput="++## #+### ++" /M "First input: "
echo Input read: "%FirstInput%"

call :ReadFormattedLine SecondInput="+++#+ ###########" /M "Second input: "
echo Input read: "%SecondInput%"

You may download the subroutine from this site.

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • This is exactly what I was looking for. I built my routine to creat a text file around this and it works great. I did need to add a few more lines of text around the user inputs that were sent to the file but got over that and things are looking good thanks for your effort this is a great answer and helped me out no end. Thanks again. – andrew davies Mar 31 '15 at 11:37
0

According to this FINDSTR (Search for strings) reference we can use following metacharacters to construct our regular expression patterns:

 ^     Line position: beginning of line
 $     Line position: end of line
 [ ]   Character class: one space
 [0-9] Range: decimal digit (n)
 [A-Z] Range: English alphabet letter in uppercase (L)

For string template: "regular expression pattern"

  • LLnn nLnnn LL: "^[A-Z][A-Z][0-9][0-9][ ][0-9][A-Z][0-9][0-9][0-9][ ][A-Z][A-Z]$"
  • LLLnL nnnnnnnnnnn: "^[A-Z]{3}[0-9][A-Z][ ][0-9]{11}$"

Unfortunately, findstr regular expressions engine does not support ´{11}´ or {3} (an additional quantifier that allows you to specify how many times a token can be repeated), so we write this terrible pattern:

"^[A-Z][A-Z][A-Z][0-9][A-Z][ ][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$"

Unfortunately, FINDSTR is limited to a maximum of 15 character class terms within a regex and using it will raise an error FINDSTR: Search string too long. (Solution below).

To be user-friendly, I'd not limit an user's input to use uppercase only and no additional spaces!

  • letter case: use a subroutine to convert variable contents to upper/lower case. The :toUcase subroutine based on Aacini's answer here;
  • spaces: FOR /F loop used to remove all superabundant spaces; moreover, in second case, to make easy user's input the horrible 11-character could be split by a space (cf. output below);
  • 15 character class terms limit: FOR /F loop used to split someVar2U variable and treat each part apart.

In next script is, for debugging and demonstrative purposes:

  • set /P command omitted: user's inputs substituted by %~1 and %~2 script command line arguments;
  • echo ...> dblank.txt redirection omitted;
  • some additional self-explaining comments.

The script:

@echo OFF >NUL
SETLOCAL enableextensions disabledelayedexpansion

:: LLnn nLnnn LL
set "someVarU=%~1"
echo [THIS IS THE STRING ENTERED] [%someVarU%]
:: remove superabundant spaces
for /F "tokens=1-3*" %%G in ("%someVarU%") do set "someVar=%%G %%H %%I%%J"
:: convert to uppercase 
call :toUcase somevar somevarU
echo(%someVarU%|FindStr /R /C:"^[A-Z][A-Z][0-9][0-9][ ][0-9][A-Z][0-9][0-9][0-9][ ][A-Z][A-Z]$">nul
echo FindStr return %errorlevel% in [%somevarU%] 

:: LLLnL nnnnnnnnnnn
set "someVar2U=%~2"
echo [THIS IS THE SECOND STRING ENTERED] [%someVar2U%]
:: remove superabundant spaces
for /F "tokens=1-2*" %%G in ("%someVar2U%") do set "someVar2=%%G %%H%%I"
:: convert to uppercase
call :toUcase somevar2 somevar2U
rem {3} not supported: echo(%someVar2U%|FindStr /R /C:"^[A-Z]{3}[0-9][A-Z][ ][0-9]{11}">nul
:: 
set /A "myErrLevel=0"
for /F "tokens=1*" %%G in ("%someVar2U%") do (
    echo(%%G|FindStr /R /C:"^[A-Z][A-Z][A-Z][0-9][A-Z]$">nul
    if errorlevel 1  set /a "myErrLevel+=10"
    echo(%%H|FindStr /R /C:"^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$">nul
    if errorlevel 1  set /a "myErrLevel+=20"
)
echo FindStr return %myErrLevel% in [%somevar2U%] 
ENDLOCAL
goto :eof


:toUcase
:: Based on https://stackoverflow.com/a/15650980/3439404 by Aacini
:: Converts variable contents to upper case
:: Usage: CALL :toUcase VAR_IN VAR_OUT
:: VAR_IN  = NAME of variable whose value is to be converted to upper case
:: VAR_OUT = NAME of variable to hold the converted value
:: Note: use variable NAMES in the CALL (i.e. pass both "by reference")
SETLOCAL enableextensions enabledelayedexpansion
set "_strToConvert=!%1!
for %%b in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    set _strToConvert=!_strToConvert:%%b=%%b!
)
:: do not break next line, keep "&" ampersands 
ENDLOCAL&set %2=%_strToConvert%&goto:eof

Output:

==>D:\bat\StackOverflow\29340733.bat " ab52  7i556    Ta  " " ebh9e 12345   123456"
[THIS IS THE STRING ENTERED] [ ab52  7i556    Ta  ]
FindStr return 0 in [AB52 7I556 TA]
[THIS IS THE SECOND STRING ENTERED] [ ebh9e 12345   123456]
FindStr return 0 in [EBH9E 12345123456]

==>D:\bat\StackOverflow\29340733.bat " 1b52  7i556    Ta  " " ebhe x2345   123456"
[THIS IS THE STRING ENTERED] [ 1b52  7i556    Ta  ]
FindStr return 1 in [1B52 7I556 TA]
[THIS IS THE SECOND STRING ENTERED] [ ebhe x2345   123456]
FindStr return 30 in [EBHE X2345123456]

==>
Community
  • 1
  • 1
JosefZ
  • 28,460
  • 5
  • 44
  • 83