Extract first character from a string - windows

I've no knowledge regarding Windows batch programming syntax. I have a text file containing user IDs which I need to delete using curl command and for that I need to extract first character of every user ID and then pass to the curl command. I know the curl command which will require two variables:
'UserID' - Read from the text file.
'firstCharacter' - Extracting first character from the User ID.
Below is the code to fetch user IDs from users.txt file:
#echo off
for /f "tokens=*" %%a in (users.txt) do call :processline %%a
pause
goto :eof
:processline
echo %*
goto :eof
:eof
Please help me with extracting the first character from the read User IDs.
Thanks.

The cmd.exe can do a limited amount of string parsing. JosefZ gave you a good place to start.
C:>echo %PROCESSOR_ARCHITECTURE%
AMD64
C:>echo %PROCESSOR_ARCHITECTURE:~0,1%
A

In a batch / command file I was always needing the first x characters or a string and ended up with many functions all doing the same thing but different names, i.e. getFirstChar, getFirstTwoChars, etc.. - so decided to make a generic function where I could pass in the number of characters I needed:
::-- getFirstXChars
:getFirstXChars
set sValIn=%1
set /a iNo=%2
set vWorkVal=%%sValIn:~0,%iNo%%%
call:getFirstX %vWorkVal% vWorkVal2
set %3=%vWorkVal2%
:getFirstX
set %2=%~1
goto:eof
to use the syntax would be
set varToTrim=ABCDEFG
call:getFirstXChars %varToTrim% 2 varToTrimAfter
#echo 1 %varToTrim%
#echo 2 %varToTrimAfter%
pause
result from command file:
1 ABCDEFG
2 AB

I just added to set variable "id" to be %%a, then I used substring notation to get the first character.
Substrings are processed by using :~start,length after the variable name and before the last % in the variable.
#echo off
for /f "tokens=*" %%a in (output.txt) do set id=%%a & call :processline %%a
pause
goto :eof
:processline
echo %id:~0,1%
goto :eof
:eof

Related

How can I restructure file names on bulk via batch script

I have 324 files on a Windows 10 machine which are named in the following pattern:
[7 Numbers] [Space] [Last name] [Space] [First name]
And I need them to be:
[Last name] [Space] [First name] [Space] [7 Numbers]
I have done some quick research and found that I could write a batch script utilizing the 'rename' function:
#echo off
rename “y:\*.txt” “???-Test1.*”
However, I was unable to find out how I can program the script to take the first 7 chracters and put them to the end.
Any help is appreciated.
Given the little detail on the exact formatting of your structures, i.e what happens in the event a surname has a split like van Halen which also now contains a space:
anyway, this will cater for the situation as you've mentioned only and not for names/surnames containing spaces.
#echo off
for /f "tokens=1-3*" %%i in ('dir /b /a-d *.txt ^| findstr /R "^[1-9]"') do echo ren "%%i %%j %%k" "%%~nk %%~nj %%~ni%%~xk"
Note this example will simply echo the command and not perform the actual rename. You need to test it first before you do the renaming. Once you are happy with the result printed to console, then remove echo from the line.
Note. findstr is important here as we need to only perform the action if the file starts with numbers. You can define the findstr filter even more if you want to be more specific. Here I just focused on numbers in the beginning of any .txt file considering no name or surname should start with a number., Unless you're 50cent or some other random rapper.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem The following setting for the source directoryis a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files\t w o"
FOR %%b IN ("%sourcedir%\??????? * *.txt") DO FOR /f "tokens=1*delims= " %%u IN ("%%~nb") DO SET /a junk=0&SET /a "junk=1%%u" 2>nul&IF !junk! geq 10000000 IF !junk! leq 19999999 ECHO REN "%%b" "%%v %%u.txt"
GOTO :EOF
Please note that this routine uses delayedexpansion
The first for puts the absolute filename of each file matching the mask into %%b
The second partitions the name part of the filename (%%~nb) into that part before the first space (token 1) to %%u and the remainder (token *) to %%v
junk is then set to 0 and then reset to the value of 1%%u. set /a will leave junk unchanged (therefore, 0) if %%u is not a numeric string (the 2>nul suppresses the error message) so if %%u is numeric, junk will be set to 10000000 ... 19999999.
Use !junk! to access the run-time value of junk, check it is within range and if so, echo the ren required.
Remove the echo keyword before the ren after checking the resultant report to actually rename the files.

FINDSTR to find text START END of string

I have string photo="999" price="10" category="1" . I want to get only 10. This means I need to the string which start price=" and ends with "
#For /F "Tokens=1*Delims==" %%A In ('FindStr /I "^price=" "C:\price.txt" 2^>NUL')Do #Set "Ver=%%~B"
#Echo(%%Ver%% = %Ver% & Pause
findstr always returns the complete line, if successful. So it's not the right tool for this task (actually, there is no tool in cmd at all that could do that this way).
But with a bit of logic, you can work around it: remove the part from the start until (including) the triggerword price (a task, the set command is happy to do), then process the rest with a for /f loop to get the desired substring:
set "string=photo="999" price="10" category="1""
echo check: %string%
echo debug: %string:*price=%
for /f tokens^=2^ delims^=^" %%a in ("%string:*price=%") do set "ver=%%~a"
echo ver=%ver%
If you are sure of the exact format of your string (in your example the searched substring is the second quoted argument, so the fourth token when splitted by ") it gets as easy as:
for /f tokens^=4^ delims^=^" %%a in ("%string%") do echo ver=%%~a
or
for /f tokens^=4^ delims^=^" %%a in (file.txt) do echo ver=%%~a
#ECHO OFF
SETLOCAL
set "string=photo="999" price="10" category="1""
:: remove quotes
set "string=%string:"=%"
for /f %%a in ("%string:* price=%") do set /a pricefound%%a
set pri
goto :eof
Since we don't have a representative sample of the file in question, we're forced to the conclusion that the requirement is to find the one and only appearance of price="anumber" in the file.
So, since findstr output, properly framed, would select this line, all we need do is process the string.
This is kind of a quick-and-dirty method; it may be adequate for OP's purpose.
First, remove the quotes from the string as they have a habit of interfering.
Next, use for /f in string-processing mode where it does its magic on the quoted string in parentheses. The string is the original string, minus quotes, so replace all characters up to "Spaceprice" with nothing and take the first token of the result, resulting in =10 assigned to %%a in the example case.
Then execute "set /a somevariablename=10" by simply concatenating the two strings.
Note that if the file contains a line like ... pricelastweek="9" ... then other measures may need to be taken.
Here's an example which tries to follow a similar methodology as your example code.
It uses FindStr to isolate any line in C:\price.txt, which includes the word price="<OneOrMoreDigits>". That line is saved as a variable named price, which is split under delayed expansion in a nested For loop, to remove everything up to, and including the first instance of the string price, leaving, in this case, ="10" category="1". The nested loop further splits that, to take the second token, using a doublequote character as the delimiter, (which should be your required value).
#For /F Delims^=^ EOL^= %%G In ('%__AppDir__%findstr.exe /IR "\<price=\"[0123456789]*\"\>" "C:\price.txt"') Do #(Set "price=%%G" & SetLocal EnableDelayedExpansion
For /F Tokens^=2^ Delims^=^" %%H In ("!price:* price=!") Do #EndLocal & Set "price=%%H")
#Echo %%price%% = %price% & Pause
Well clearly you need to match lines that contain price=" as there may be other lines.
What's unclear is if you need match 10 exactly, or just want that to be any number.
It seems likely you just want to match any number and grab it.
This is done easily with:
#For /F "Tokens=4 Delims=^= " %%A In ('
TYPE "C:\price.txt" ^| FIND /I "price="""') Do #(
Set "Ver=%%~A" & CALL SET Ver &Pause )
While is you need to match Price="10", which seems less useful, but at least one person took that meaning and your wording is a little unclear so I will add that was well:
#For /F "Tokens=4 Delims=^= " %%A In ('
TYPE "C:\price.txt" ^| FIND /I "price=""10"""') Do #(
Set "Ver=%%~A" & CALL SET Ver &Pause )
Note in all examples I left in the # symbols since I assume this is you being clever, and leaving ECHO ON and only removing the # symbols when you want to debug some specific thing you are doing.
However, in case not, it's worth pointing out that in a script it's usually easiest to place ECHO OFF at the start of the script instead of putting an # at the beginning of each statement to stop it from echoing.
Cheers! :)

Create new string from 1st character of each word of a multi word string

I have a need for a Windows NT command script to do the following:
- Read variable string from command line
- Take that variable and create new string based off 1st byte of each word
The incoming string in the Windows NT command script is %1.
The string may vary in length and number of words, but always ends with (something here) [something there].
Example - Incoming value from command line including quotes:
"This is my string for a new name (comment) [comment 2]"
The string I need to create is:
Timsfann
These characters are from the 1st letter in each of the words in the above string and stopping when it gets to the parenthesis in (comment).
The above string will be concatenated with a date/time string to create a unique filename. The finished string should be set to a system variable so that programs can find the finished value.
Any help would be appreciated.
I've been attempting using a FOR loop, but can't seem to get it to work as desired.
#Crimsyn, if it's easier for you to understand, here's another one of the few ways, which doesn't use delayed expansion or the FOR statement:
#Echo Off
Call :Loop %~1
Echo(%oStr%&Pause
Exit/B
:Loop
If "%~1"=="" GoTo :EOF
Set "iStr=%~1"
If "%iStr:~,1%"=="(" GoTo :EOF
Set "oStr=%oStr%%iStr:~,1%"
Shift&GoTo Loop
Another one! Although simpler and shorter, this method could be harder to understand... ;)
#echo off
setlocal EnableDelayedExpansion
set "str=%~1 "
set "str=%str:(= " & rem %
set "result="
set "word=%str: =" & set "result=!result!!word:~0,1!" & set "word=%"
echo %result%
Hint: execute it with echo on
Just one of a few ways you could do this.
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1 delims=(" %%G IN ("%~1") do set "line=%%G"
FOR %%G IN (%line%) DO (
set tline=%%G
set code=!code!!tline:~0,1!
)
echo %code%
pause

How to get a specific line from command output in batch script into a variable?

I'd like to get a changelist description from perforce, which involves calling a p4 describe -s , so the ouput would be as below. Is there a way to get (trimmed characters from the third line) from the output just using windows batch syntax?
Change 6582 by username on 2016/12/06 00:35:41
MyChangeDescription
Affected files ...
... //depot/foo.txt#7 edit
... //depot/foo2.txt#6 edit
Give this a shot:
p4 -Ztag -F %Description% change -o 6582
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q40986156.txt"
FOR /f "usebackqskip=2tokens=*" %%a IN ("%filename1%") DO (
SET "desc=%%a"
GOTO show
)
:show
ECHO "%desc%"
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q40986156.txt containing your data for my testing.
This uses a file as input. Since I don't have access to perforce, I can't test it but
#ECHO OFF
SETLOCAL
FOR /f "skip=2tokens=*" %%a IN ('p4 describe -s') DO (
SET "desc=%%a"
GOTO show
)
:show
ECHO "%desc%"
GOTO :EOF
should be equivalent.
Simply, read the output of the command, skip the first 2 lines, tokenise the entire line, skipping leading spaces. Assign the string found to a variable and immediately exit the loop.

Batch Script Find String in String with a twist

I am trying to do this in a batch script, which should be simple, but after spending a couple of hours on it I am no closer to a solution.
If the CMD parameter contains a series of letters, I want to surround each letter with single quotes and separate by commas. For example, if the user enter this:
MYTEST.CMD ABCDEF
I want to create a string that looks like this:
'A','B','C','D','E','F'
The same as if they had entered this in the CMD line:
MYTEST.CMD "'A','B','C','D','E','F'"
Fairly easy, actually:
#echo off
set "LETTERS=%~1"
set OUTPUT=
if not defined LETTERS goto usage
:loop
if defined OUTPUT set "OUTPUT=%OUTPUT%,"
set "OUTPUT=%OUTPUT%'%LETTERS:~0,1%'"
set "LETTERS=%LETTERS:~1%"
if defined LETTERS goto loop
echo.%OUTPUT%
goto :eof
:usage
echo Please pass a few letters as argument, e.g.
echo. %~0 ABC
goto :eof
Let's dissect it a little:
We first store the argument in the variable LETTERS.
Then we initialise our output string to an empty string.
Then follows a loop that appends the first letter from LETTERS to OUTPUT in the proper format (with a comma before if OUTPUT is not empty) and removes that letter from LETTERS.
When LETTERS is empty, we exit the loop and print the result.
And just for the fun of it, the same as a PowerShell function:
function Get-LetterList([string]$Letters) {
([char[]]$Letters | ForEach-Object { "'$_'" }) -join ','
}
The Batch file below use an interesting trick I borrowed from this post that convert the Ascii (1-byte) characters into Unicode 2-bytes characters via cmd /U (inserting a zero-byte between characters), and then split the zero-bytes in individual lines via find command:
#echo off
setlocal EnableDelayedExpansion
set "output="
for /F "delims=" %%a in ('cmd /D /U /C echo %~1^| find /V ""') do (
set "output=!output!,'%%a'"
)
set output="%output:~1%"
echo %output%

Resources