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%
Related
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
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
I have a csv file populated with name, address, and postcode. A large number of the postcodes do not have the required space in between e.g LU79GH should be LU7 9GH and W13TP should be W1 3TP. I need to add a space in each postcode field if it is not there already, the space should always be before the last 3 characters.
What is the best way to solve this via windows command line?
Many Thanks
You can do this with for /f as follows:
#echo off
setlocal enabledelayedexpansion
if "%~1" equ "" (echo.%~0: usage: missing file name.& exit /b 1)
if "%~2" neq "" (echo.%~0: usage: too many arguments.& exit /b 1)
for /f %%i in (%~1) do (echo.%%i& goto :afterheader)
:afterheader
for /f "skip=1 tokens=1-3 delims=," %%i in (%~1) do (
set name=%%i
set address=%%j
set postcode=%%k
set postcode=!postcode: =!
echo.!name!,!address!,!postcode:~0,-3! !postcode:~-3!
)
exit /b 0
Demo:
> type data.csv
name,address,postcode
n1,a1,LU79GH
n2,a2,W13TP
n1,a1,LU7 9GH
n2,a2,W1 3TP
> .\add-space.bat data.csv
name,address,postcode
n1,a1,LU7 9GH
n2,a2,W1 3TP
n1,a1,LU7 9GH
n2,a2,W1 3TP
You can redirect the output to a file to capture it. (But you can't redirect to the same file as the input, because then the redirection will overwrite the input file before it can be read by the script. If you want to overwrite the original file, you can redirect the output to a new file, and then move the new file over the original after the script has finished.)
Using windows you could do something with Powershell.
$document = (Get-Content '\doc.csv')
foreach($line in $document) {
Write-Host $line
// Add logic to cut out exactly what column your looking at with
$list = $line -split","
// Then use an if statement and regular expression to match ones with no space
if($list[0] -match ^[A-Z0-9]$){
// item has no space add logic to add space and write to file
}else{
// item has space or doesnt match the above regular expression could skip this
}
}
Pretty good documentation online check out http://ss64.com/ps/ for help with powershell.
Parsing CSV can be tricky because a comma may be a column delimiter, or it may be a literal character within a quoted field.
Since your postcode is always the last field, I would simply look at the 4th character from the end of the entire line, and if it is not already a space, than insert a space before the last 3 characters in the line. I will also assume that the first line of the file lists the field names, so you don't want to modify that one.
Using pure batch (assuming no values contain !):
#echo off
setlocal enableDelayedExpansion
set "skip=true"
>"test.csv.new" (
for /f "usebackq delims=" %%A in ("test.csv") do (
set "line=%%A"
if "!line:~-4,1!" equ " " set "skip=true"
if defined skip (echo !line!) else (echo !line:~0,-3! !line:~-3!)
set "skip="
)
)
move /y "test.csv.new" "test.csv" >nul
The solution is simpler if you use my JREPL.BAT regular expression text processor. It is a pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. The following one liner will do the trick:
jrepl "[^ ](?=...$)" "$& " /jbegln "skip=(ln==1)" /f test.csv /o -
Use CALL JREPL ... if you use the command within another script.
If I get my parameter with %1 and it is "Server" how can I add a + sign after every letter?
So my result would be "S+e+r+v+e+r"?
I think Batch file to add characters to beginning and end of each line in txt file this is a similar question but I don't know how to change the code for this purpose.
Any help would be great!
I'm pretty sure this has been asked and answered before, but I couldn't find it.
There is a really cool (and fast) solution that I saw posted somewhere. It uses a new cmd.exe process with the /U option so output is in unicode. The interesting thing about the unicode is that each ASCII character is represented as itself followed by a nul byte (0x00). When this is piped to MORE, it converts the nul bytes into newlines!. Then a FOR /F is used to iterate each of the characters and build the desired string. A final substring operation is used to remove the extra + from the front.
I tweaked my memory of the code a bit, playing games with escape sequences in order to get the delayed expansion to occur at the correct time, and to protect the character when it is appended - all to get the technique to preserve ^ and ! characters. This may be a new twist to existing posted codes using this general technique.
#echo off
setlocal enableDelayedExpansion
set "str=Server bang^! caret^^"
set "out="
for /f delims^=^ eol^= %%A in ('cmd /u /v:on /c echo(^^!str^^!^|more') do set "out=!out!+^%%A"
set "out=!out:~1!"
echo Before: !str!
echo After: !out!
--OUTPUT---
Before: Server bang! caret^
After: S+e+r+v+e+r+ +b+a+n+g+!+ +c+a+r+e+t+^
This batch file should do it:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET Text=%~1
SET Return=
REM Batch files don't have a LEN function.
REM So this loop will process up to 100 chars by doing a substring on each.
FOR /L %%I IN (0,1,100) DO (
CALL SET Letter=!Text:~%%I,1!
REM Only process when a letter is returned.
IF NOT "!Letter!" == "" (
SET Return=!Return!+!Letter!
) ELSE (
REM Otherwise, we have reached the end.
GOTO DoneProcessing
)
)
:DoneProcessing
REM Remove leading char.
SET Return=%Return:~1,999%
ECHO %Return%
ENDLOCAL
Calling with Test.bat Server prints S+e+r+v+e+r to the console.
I call the file I want to search in input.txt and the string I want to find mystring.
Example content of input.txt (real input.txt)
randomstring1<>"\/=:
randomstring2<ORIGINAL>mystring</ORIGINAL>randomstring3
mystring is surrounded by the strings <ORIGINAL> and </ORIGINAL> that must be searched for
The string between both ORIGINAL-tags should be copied to clipboard (using | clip)
mystring and the tags occur only once. But they have no fixed position
all strings can contain special characters (<, >, ", \, /, =, :)
I read a lot of other SO questions but to be honest: the FOR-loop and SET-command syntax was too awkward for me. I guess my best shot will be the FINDSTR command. But maybe it is also possible with some help of RegEx expressions.
I do not want to use VBscript, Powershell, SED, FART, AWK, grep or any other additional tool.
Please be so kind and explain the difficult parts if you post a solution.
I want to understand it and maybe its helpful for others too.
My last attempt before I've given up was this test.cmd
#echo off
set "x=randomstring1<>"\/=:randomstring2<ORIGINAL>mystring</ORIGINAL>randomstring3"
set "x=%x:*<ORIGINAL>=%"
set "x=%x:</ORIGINAL>*=%"
set x=%x:~2%
echo %x%
pause
#echo off
rem Let findstr to find the LINE you want (only once):
for /F "delims=" %%a in ('findstr "<ORIGINAL>" input.txt') do set "line=%%a"
ECHO LINE: "%line%"
rem Change left delimiter by {
set "line=%line:<ORIGINAL>={%"
rem Change right delimiter by }
set "line=%line:</ORIGINAL>=}%"
ECHO STRING DELIMITED: "%LINE%"
rem Get second token delimited by { and }
for /F "tokens=2 delims={}" %%a in ("%line%") do set string=%%a
ECHO STRING: "%STRING%"
rem Copy string to clipboard
REM echo %string%| clip
Output:
LINE: "randomstring2<ORIGINAL>mystring</ORIGINAL>randomstring3"
STRING DELIMITED: "randomstring2{mystring}randomstring3"
STRING: "mystring"
As an option, you may delete from beginning of line until left delimiter:
set "line=%line:*<ORIGINAL>=%"
... and get the FIRST token separated by any delimiter you wish (ie: }):
for /F "delims=}" %%a in ("%line%") do set string=%%a