I've got the following pattern :
[AAAAAA] Title - 1234 (AAAAAA)[Something that changes].mkv
I'd like to only keep :
Title - 1234
The AAAAAA parts are always the same : 10 letters for the first set, and 4 numbers + 1 letter for the second set.
The Title - 1234 part changes constantly.
The [Something that changes] part changes constantly.
Is there a way to remove what's before ] and after (, so that I only keep the Title and the Episode n° ?
I don't mind making multiple "rename" commands (I do that in batch anyway)
Any way to do that ?
Thanks !
use this string substitute:
This find the first "]" and trim everything from beginning
Then trim all after the first "("
#echo off
setlocal enabledelayedexpansion
for %%F in (*.mkv) do (
set "f=%%~F"
set "f=!f:*]=!"
call :trim
echo ren "%%~F" "!f!%%~xF"
)
pause
goto :eof
:trim
SET f=%f:(=&rem.%
goto :eof
output:
C:\Users\fposc\AppData\Local\Temp>ren1
ren "[AAAAAA] Title - 1234 (AAAAAA)[Something that changes].mkv" " Title - 1234 .mkv"
Premere un tasto per continuare . . .
If you want to remove leading and trailing spaces you can include them in the code like this:
#echo off
setlocal enabledelayedexpansion
for %%F in (*.mkv) do (
set "f=%%~F"
set "f=!f:*] =!"
call :trim
echo ren "%%~F" "!f!%%~xF"
)
pause
goto :eof
:trim
SET f=%f: (=&rem.%
goto :eof
output:
C:\Users\fposc\AppData\Local\Temp>ren1
ren "[AAAAAA] Title - 1234 (AAAAAA)[Something that changes].mkv" "Title - 1234.mkv"
Premere un tasto per continuare . . .
Test this and when is ok you can remove the "echo" and left "ren" command or copy the output in a file and then execute.
Use the -replace regex operator:
Get-ChildItem -Filter *.mkv |Rename-Item -NewName {"$($_.BaseName -replace '^\[\p{L}{10}\]\s*([^\(]+).*$','$1').mkv"}
The pattern used
^\[\p{L}{10}\]\s*([^\(]+).*$
... matches:
^ # Start of string
\[ # Literal `[`
\p{L}{10} # 10 consecutive letters
\] # Literal `]`
\s* # Any whitespace
([^\(]+) # Capture the longest possible sequence on non-`(` chars
.* # the rest of the string (eg. `(ABCD1) something something.mkv`)
$ # End of string
We then replace the whole thing with everything we captured in between the ] and (.
Related
What I need is the first sequence of a number in a listing:
The command:
for /f "delims=" %%a in (notas.txt) do #echo %%a
Returns:
Compra cfme NF 12345 de 123 CIA ABC
Pgto dupl. 12345 - 123 CIA ABC
Compra cfme NFS 654321-CIA CBC
Pgto NF 654321 de CIA CBC
But what I need is:
12345
12345
654321
654321
Thanks in advance
There are numerous PowerShell solution/techniques that can perform what is required.
The switch statement can be used with the -File and -Regex parameters.
switch -Regex -File notas.txt {
'\d+' { $Matches[0] }
}
You can also use the Match method from the regex class:
Get-Content notas.txt | Foreach-Object {
[regex]::Match($_,'\d+').Value
}
Both solutions rely on regex matching with \d+ matching one or more consecutive digits. Since we are doing a single match per line, the first match is the only match returned. The regex class method Matches returns multiple matches per string input.
With a Batch file using regex in vbscript you can do something like this :
Demo Here
#echo off & color 0A
Title Extract Numbers from String using Regex with vbscript
Set "InputFile=%~dp0notas.txt"
Set "OutPutFile=%~n0_OutPutFile.txt"
Call :Extract_Number "%InputFile%" CON
Call :Extract_Number "%InputFile%" "%OutPutFile%"
TimeOut /T 3 /NoBreak>nul
If Exist "%OutPutFile%" Start "" "%OutPutFile%" & Exit
::-----------------------------------------------------------------------------------
:Extract_Number <Input> <OutPut>
(
echo WScript.StdOut.WriteLine Extract_Number(Data^)
echo Function Extract_Number(Data^)
echo Data = "%~1"
echo Data = WScript.StdIn.ReadAll
echo Set re = New RegExp
echo re.Global = True
echo re.IgnoreCase = True
echo re.Pattern = "\d{5,}"
echo For Each Match in re.Execute(Data^)
echo Number = Number ^& Match.Value ^& vbCrLF
echo Next
echo Extract_Number = Number
echo End Function
)>"%tmp%\%~n0.vbs"
cscript //nologo "%tmp%\%~n0.vbs" < "%~1" > "%~2"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
Exit /B
::----------------------------------------------------------------------------------
This first code does what your question asks, but not what your expected results show:
#echo off
:: Pass the entire line to a subroutine
for /f "delims=" %%a in (notas.txt) do call :process %%a
goto :eof
:process
:: Check if we've evaluated the entire line
if "%1"=="" (
echo No number was found in this line
goto :eof
)
:: Check if the current parameter is only numbers
:: If it is, then echo and move on to the next line
:: If not, use shift to evaluate the next parameter
echo %1|findstr /i /r "[^0-9]" >nul && shift && goto :process
echo %1
goto :eof
2 things. First, I don't know what you want to do if a number isn't found in the line. In the code above I just echo "No number was found in this line".
Second, I presumed "number" to be fully delimited with standard spaces as delimiters. Thus, the code above does NOT return 654321 from the line Compra cfme NFS 654321-CIA CBC because 654321-CIA is not a number delimited by spaces. If you want additional delimiters, then change this line above:
for /f "delims=" %%a in (notas.txt) do call :process %%a
to:
for /f "tokens=1-10 delims=-., " %%a in (notas.txt) do call :process %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j
adding whatever delimiters you want (don't forget a space before the double quote). This line is good for up to 10 entries on a given line. Going up to 26 using tokens=1-26 and %%a through %%z is pretty easy.
Finally -- if you want to pull a non-delimited number -- then that would be a completely different approach. An example would be getting 1356 from PC1356 NLA LOA; or getting 35232 from PC LI-D 35232NDA TTH.
(EDITED) How can I read data from a text file and assign certain parts of it to variables? In the lines below, for example, I want to assign the data to variables where indicated but ignore the header line, the preface word "DATA:" and any quotation marks.
HEADER (ignore)
DATA: "set text inside quotes to VAR1"
DATA: "set text inside quotes to VAR2"
DATA (etc.)
The code I'm using is:
setlocal enabledelayedexpansion
set COUNT=0
for /f "usebackq delims=" %%a in ("data.txt") do (
set "INPUT=%%a"
set /a COUNT=!COUNT!+1
echo !INPUT! | findstr /i /c:"HEADER" > nul
if errorlevel 1 (
set "INPUT=!INPUT:DATA:=!"
set "INPUT=!INPUT:"=!"
set VAR!COUNT!=!INPUT!
echo Variable !COUNT! = !VAR!!COUNT!
)
)
My expected output is
Variable 1 = set text inside quotes to VAR1
Variable 2 = set text inside quotes to VAR2
but what I get is
Variable 2 = 2
Variable 3 = 3
Variable 4 = 4
What am I doing wrong?
I took your code and fixed it up.
In particular:
I switched the findstr to find all lines that do not match HEADER
I used arrays to store the variables.
It may need some minor tweaks to get it exactly as you want it, but I think I've given you a working outline.
#echo off
setlocal enabledelayedexpansion
set COUNT=0
for /f "tokens=*" %%a in ('findstr /i /v HEADER data.txt') do (
set "INPUT=%%a"
set /A COUNT=!COUNT!+1
set "INPUT=!INPUT:DATA:=!"
set VAR[!COUNT!]=!INPUT!
call echo Variable !COUNT! = %%VAR[!COUNT!]%%
)
Output:
Variable 1 = "set text inside quotes to VAR1"
Variable 2 = "set text inside quotes to VAR2"
Variable 3 = DATA (etc.)
To match lines that have leading spaces, use switches:
findstr /V /R /C:"^ *HEADER"
The regular expression means:
^ : Beginning of line
[space] : a literal space
* : the previous character (space) repeated as many times as needed
HEADER : the text to find after leading spaces
The switches mean:
/R Use Regular Expressions
/C: Use this search-string
/V Show all lines that do NOT match this expression.
I want create a batch to replace spaces with a + sign if the space is in between quotes. Then I want to remove the quotes from a text file. How can I accomplish this?
So I want to change a line like this:
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" "-" www.vietnam.ttu.edu 200 200 200 1868 0
To this line.
2016-01-11 14:45:09 Server 127.0.0.1 GET /global/images/logo_small.jpg - 80 - 173.252.120.117 facebookexternalhit/1.1+(+http://www.facebook.com/externalhit_uatext.php) - www.vietnam.ttu.edu 200 200 200 1868 0
Thanks
You could use JREPL.BAT to arrive at a very concise and efficient solution. JREPL is a pure script based (JScript/batch) regular expression text processing utility that runs on any version of Windows from XP onward.
jrepl "\q| " "q=!q;''|q?'+':' '" /j /x /t "|" /jbegln "q=false" /f test.txt /o -
For this solution I use the /T option, which is very similar to the unix tr utility, or the sed y command.
I define two search terms, the first for a quote (The \X option enables the \q escape sequence), and the second for a space.
The /J option treats replacement strings as JScript. The first replacement string for the quote toggles a "q" variable TRUE or FALSE, and replaces the quote with an empty string. The second replacement string conditionally replaces the space with a plus or space, depending on the state of the "q" variable.
The /JBEGLN option initializes the "q" variable to FALSE at the beginning of each line.
The /F option specifies the input file, and the /O - option specifies that the output overwrites the original file.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q34732271.txt"
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO ECHO %%a&SET "line="&CALL :process %%a
GOTO :EOF
:process
SET "addition=%~1"
IF not DEFINED addition ECHO %line:~1%&GOTO :eof
IF "%~1"==%1 (
REM quoted
SET "line=%line% %addition: =+%"
) ELSE (
SET "line=%line% %addition%"
)
shift
GOTO process
You would need to change the setting of sourcedir to suit your circumstances.
I used a file named q34732271.txt containing your data for my testing.
The echo %%a shows your one line of data on the screen and the echo within the :process routine shows that line processed.
Batch is not an ideal language to process strings as it exhibits sensitivity to many symbols. This process should work provided you are happy to have space-strings compressed and the source string does not contain , ;,tab % or any other symbol that cmd treats specially.
Here is a pure batch-file solution that walks through the characters in each line in file line.txt, replaces all SPACEs in between a pair of quotation marks "" by + signs and stores the result in text_new.txt. The input string may contain any characters, even special ones:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define global constants here:
set "INFILE=line.txt"
set "OUTFILE=line_new.txt"
set "SEARCH= "
set "REPLACE=+"
set "KEEPQUOTES="
set "QUOTE="""
set "QUOTE=%QUOTE:~,1%"
set "QFLAG="
> "%OUTFILE%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
set "LINE=%%L"
call :SUB LINE
)
)
endlocal
exit /B
:SUB
setlocal EnableDelayedExpansion
set "LINE=!%1!"
set "LINENEW="
set /A "POS=0"
:LOOP
set "CHAR=!LINE:~%POS%,1!"
set /A "POS+=1"
if not defined CHAR (
echo(!LINENEW!
endlocal
exit /B
)
if "!CHAR!"=="!QUOTE!" (
if defined QFLAG (
set "QFLAG="
) else (
set "QFLAG=Quoted"
)
if defined KEEPQUOTES (
set "LINENEW=!LINENEW!!CHAR!"
)
) else if defined QFLAG (
if "!CHAR!"=="!SEARCH!" (
set "LINENEW=!LINENEW!!REPLACE!"
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
) else (
set "LINENEW=!LINENEW!!CHAR!"
)
goto :LOOP
I need to parse a file that has the following format:
A + tags/RWSTestConsole_tag1/
(from trunk/RWSTestConsole/:r776)
So I'm using a FOR /F loop with a counter and inspecting the tokens based on whether I'm looking at line 1 or line 2. Everything works fine except the first token for line 2 includes the leading spaces (" from") and a) I thought the delims on my FOR would take care of spaces and b) theoretically I could just compare to a constant string that is set to " from" but that's kind of hokey.
This is my FOR command:
for /F "tokens=1,2,3,4,5 delims=():/ " %%a in (svn.txt) DO (
Is there a change I can make to the FOR command to ignore the spaces? If not is there a way to trim the token inside the FOR loop's DO clause so I only get the word without the leading spaces?
Edit:
This is output from a Subversion SVNLOOK command in a script that is managing whether or not to allow a "tag" to be created. The output can be 1 line that must be formatted as:
D /tags/tagfoldername/
If it's one line but it's not a delete for the actual tag folder then it's an error. This case is handled.
If it's more than 2 lines it's a list of files and that's an error. I have that handled.
The case I'm having problems with is if it is 2 lines it needs to be in the format shown above:
A + tags/RWSTestConsole_tag1/
(from trunk/RWSTestConsole/:r776)
Where col 1 = "A". col 3 = "+", col 5 = "tags" and the remainder of line one is the tag folder name. The second line is the source of the create request so it has to start with "from", followed by "trunk", "branches" or "tags" followed by a single-level folder name and a revision number.
I used the FOR command as described above. In the DO clause I look at a counter to tell if I'm parsing line 1 or line 2. Line 1 is simple, I have all the logic to handle it.
Line 2 is parsed by the same FOR command and the first token (%%a) removes the "{" from delims, but leaves behind all the leading blanks so I get back %%a=" from".
I need to know if there's a way I can modify the FOR command to remove the blanks or a way to trim %%a within the FOR DO clause to remove the blanks.
Edit 2: FOR Loop Code
set c=1
for /F "tokens=1,2,3,4,5 delims=():/ " %%a in (svn.txt) DO (
echo op=%%a, %%b, %%c, %%d, %%e
if !c!==1 (
set rc1=0
if /I %%a EQU A (
if "%%b" EQU "+" (
if [%%e] EQU [] (
echo Tag from a Copy Op
set rc1=0
) else (
echo Found a subfolder: %%e - not a tag delete
set rc1=1
)
) else (
echo Tag not a Copy
set rc1=1
)
)
)
if !c!==2 (
set rc2=0
set str1=%%a
echo String replace 1 = !str!
set str2=!str1:~-4!
echo String Replace 2 *!str2!*
if /I !str2! EQU FROM (
set isvalid=false
if %%b EQU trunk set isvalid=true
if %%b EQU branches set isvalid=true
if %%b EQU tags set isvalid=true
if !isvalid! EQU true (
set rc2=0
) else (
set rc2=1
echo Invalid source for Tag Creation
)
) else (
set rc2=1
echo Tag not FROM
)
)
set /a c+=1
)
echo RC1=!rc1!
echo RC2=!rc2!
set /a rc=!rc1!+!rc2!
echo final RC = !rc!
I have the following string inside my Windows batch file:
"-String"
The string also contains the twoe quotation marks at the beginning and at the end of the string, so as it is written above.
I want to strip the first and last characters so that I get the following string:
-String
I tried this:
set currentParameter="-String"
echo %currentParameter:~1,-1%
This prints out the string as it should be:
-String
But when I try to store the edited string like this, it fails:
set currentParameter="-String"
set currentParameter=%currentParameter:~1,-1%
echo %currentParameter%
Nothing gets printed out. What do I do wrong?
This really is strange. When I remove the characters like this it works:
set currentParameter="-String"
set currentParameter=%currentParameter:~1,-1%
echo %currentParameter%
it prints out:
-String
But actually my batch is a bit more complicated and there it does not work. I will show what I programmed:
#echo off
set string="-String","-String2"
Set count=0
For %%j in (%string%) Do Set /A count+=1
FOR /L %%H IN (1,1,%COUNT%) DO (
echo .
call :myFunc %%H
)
exit /b
:myFunc
FOR /F "tokens=%1 delims=," %%I IN ("%string%") Do (
echo String WITHOUT stripping characters: %%I
set currentParameter=%%I
set currentParameter=%currentParameter:~1,-1%
echo String WITH stripping characters: %currentParameter%
echo .
)
exit /b
:end
And the output is:
.
String WITHOUT stripping characters: "-String"
String WITH stripping characters:
.
.
String WITHOUT stripping characters: "-String2"
String WITH stripping characters: ~1,-1
.
But what i want is:
.
String WITHOUT stripping characters: "-String"
String WITH stripping characters: -String
.
.
String WITHOUT stripping characters: "-String2"
String WITH stripping characters: -String2
.
Hope this will help you.
setlocal enabledelayedexpansion
echo String WITHOUT stripping characters: %%I
set currentParameter=%%I
set currentParameter=!currentParameter:~1,-1!
echo String WITH stripping characters: !currentParameter!
You are modyfing a variable inside a parenthesized block. Watch out - the new value will not be used within the same block (unless you delimit the variable with ! instead of % - and running in the enabledelayedexpansion mode).
Or just extract the couple of lines into another sub-function, using a plain sequence of lines insted of ( )
greets, Stach
This script takes advantage of ENABLEDELAYEDEXPANSION.
If you don't know, batch scripts execute for and if commands all in one; hence if you do:
if true==true (
#echo off
set testvalue=123
echo %testvalue%
pause >NUL
)
You wont output anything, because when echo %testvalue% is executed, it has not recognized the testvalue has been changed.
Using delayedexapnsion allows the script to read that value as it is now, and forget the problem I stated before. You use it just like %testvalue%, but you may do !testvalue! to fix this:
if true==true (
#echo off
set testvalue=123
echo !testvalue!
pause >NUL
)
Would echo 123.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set string="-String","-String2"
Set count=0
For %%j in (%string%) Do Set /A count+=1
FOR /L %%H IN (1,1,%COUNT%) DO (
echo .
call :myFunc %%H
)
exit /b
:myFunc
FOR /F "tokens=%1 delims=," %%I IN ("%string%") Do (
echo String WITHOUT stripping characters: %%I
set currentParameter=%%I
set currentParameter=!currentParameter:~1,-1!
echo String WITH stripping characters: !currentParameter!
echo .
)
exit /b
:end
~ Alex
I had similar problem but it solved by removing spaces between
Ex : set FileName=%Name:~0,11% # Working as No space before and after '='
Ex : set FileName = %Name:~0,11% # Not Working as space before OR after '='
So please try by remove spaces, It should work
Note: command line should be reopen to get refresh the background values else it shows the same output as it is stored in temp