Batch Script - Delete Columns in csv - csv

I do need a batch script who will remove all columns in a csv, except column 1,2 and 5
My Code:
(for /f "tokens=1,2,5 delims=;" %%i in (Input.csv) do echo %%i,%%j,%%k) > Output.csv
Input CSV
1;2;3;4;5;6;7;8;9;10
10160;"Some Name";"Something:0.8";;5;;;;;XY
Expected Output:
1;2;5
10160;"Some Name";5
Real Output
1,2,5
10160,"Some Name",XY
Does anyone have any idea why it keeps the tenth column in the second line instead of the fifth?

SETLOCAL ENABLEDELAYEDEXPANSION
(FOR /f "delims=" %%b IN (Input.csv) DO SET "line=%%b"&SET "line=!line:;;=; ;!"&for /f "tokens=1,2,5 delims=;" %%i in ("!line:;;=; ;!") do echo %%i,%%j,%%k)
The problem is that a sequence of delimiters is considered as a single delimiter, so you need to change each delimiter pair so that it contains a string, and repeat the operation for any remaining delimiter-pairs.
Obviously, you would need to take action to take care of a reported field that now contains a single space, and this will alter any quoted field that contains ;;
Note also that any data containing ! or % is likely to be corrupted and certain other symbols (such as &) may also yield unexpected results. If the data is restricted to alphamerics, spaces, commas, etc. it should be fine.

Related

Remove columns from CSV Batch file

I'm trying to remove all columns in a csv file except columns 2, 3, 5, and 11
I'm having trouble with column 11.
This is my batch file:
#Echo off
(for /f "delims=" %%A in (test.csv) do Call :Split %%A
) > test_New.csv
goto :Eof
:Split
Echo(%2,%3,%5,%11
It works apart from column 11 which returns column 1.
I've tried %11% but does not work either.
Thanks
As others have already said, Batch doesn't support positional parameters greater than 9. While there are ways around that (shift /n comes to mind), a much better way of handling situations like these is to use a tokens option for for /f:
#echo off
(
for /f "tokens=2,3,5,11 delims=," %%i in (test.csv) do echo:%%i,%%j,%%k,%%l
) >"test_New.csv"
Each token causes an additional variable name to be allocated, thus the first token (#2) becomes %%i, the second (#3) %%j and so on. See for /? for further details.

Change character in batch file

Currently i have a csv export with the following output
number;sentence;text;text;text;text;text;text;18.05.2012;time;text;text;number
number;sentence;text;text;text;text;text;text;18.05.2012;time;text;text;number
number;sentence;text;text;text;text;text;text;#;time;text;text;number
number;sentence;text;text;text;text;text;text;#;time;text;text;number
Notice that it sometimes happens that a date is not present, instead "#" has been inserted. The # is also present in other parts of the CSV file, however this shouldn't be impacted. Which currently happens
#echo off
setlocal enableextensions enabledelayedexpansion
(for /f "skip=4 tokens=1-9* delims=," %%f in (input.csv) do if not "%%f"=="" (
set "line=%%f"
set "line=!line:#"=!"
echo(!line!
)) > output.csv
endlocal
Any pointers where i go wrong?
I guess, you didn't quite understand the "tokens" thing. The first token is set to the given variable (%%a), the next tokens are assigned to the (alphabetically) following variables (%%b, %%c, ...). You need to change the ninth token (%%i), so you have to retrieve tokens 1 to 9 and * for "the rest". Also your delimiter was wrong (your text file has ;, so you need delims=;)
#echo off
setlocal enableextensions enabledelayedexpansion
(for /f "skip=4 tokens=1-9* delims=;" %%a in (input.csv) do (
if "%%i"=="#" (set "data=") else (set "data=%%i")
echo(%%a;%%b;%%c;%%d;%%e;%%f;%%g;%%h;!data!;%%j
)) > output.csv
endlocal
(Of course you also could start with %%f, but then your ninth token is %%n - it's easier to read when you start with a)
Keep in mind, consecutive delimiters are treated as one. So if you have empty fields (...;text;;text;...) your tokenization goes wild.

Deleting/replacing characters delimited by commas

I'm trying to delete by batch or vbs text delimited by commas (CSV) that are always in the same position. It would not affect the first line, only lines 2 onwards.
Example text from file:
Code,Batch,File #,Reg Hours,O/T,Cost Number,Rate,Earnings,Earnings,Memo Code,Memo Amount,Earnings Code,Earnings Amount,Hours Code,Hours Amount,Earnings Code,Earnings Amount,Adjust Code,Adjust Amount
ABC,123,3980 ,78.52,,12331,10.00,,,,,,,,
ABC,123,4026 ,29.38,,12331,10.00,,,,,,,,
ABC,123,5065 ,64.46,,12331,10.00,,,,,,,,
ABC,123,5125 ,80.00, 0.54,12331,11.00,,,,,,,,
I would like to end up with text:
Code,Batch,File #,Reg Hours,O/T,Cost Number,Rate,Earnings,Earnings,Memo Code,Memo Amount,Earnings Code,Earnings Amount,Hours Code,Hours Amount,Earnings Code,Earnings Amount,Adjust Code,Adjust Amount
ABC,123,3980 ,78.52,,12331,,,,,,,,,
ABC,123,4026 ,29.38,,12331,,,,,,,,,
ABC,123,5065 ,64.46,,12331,,,,,,,,,
ABC,123,5125 ,80.00, 0.54,12331,,,,,,,,,
The only difference is the Rate area. It is the 7th separated value from the left, or 9th from the right. The first line remains intact.
Is there a way for the batch/vbs to determine the comma separated value position, delete the value or replace it with 'nothing', and ignore the first line?
For this example, we can assume the file will always be named file.csv, and located in D:\location - 'D:\location\file.csv'
Thank you!
REM <!-- language: lang-dos -->
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q46534752.txt"
SET "outfile=%destdir%\outfile.txt"
:: Remove the output file
DEL "%outfile%" >NUL 2>nul
:: To reproduce the first line intact
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO >"%outfile%" ECHO %%a&GOTO hdrdone
:hdrdone
(
REM to process the header line, remove the "skip=1" from the "for...%%a" command
FOR /f "usebackqskip=1delims=" %%a IN ("%filename1%") DO (
REM step 1 - replace all commas with "|," to separate separators
SET "line=%%a"
SET "line=!line:,=|,!"
FOR /f "tokens=1-7*delims=|" %%A IN ("!line!") DO (
SET "line=%%A%%B%%C%%D%%E%%F%%H"
ECHO !line:^|=!
)
)
)>>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q46534752.txt containing your data for my testing.
Produces the file defined as %outfile%
Processing of the header line is an issue. The code as presented should do as you ask, but it seems illogical to retain the column name in the resultant file when the process is intended to remove that column. To process the header line also, delete the first for line and remove the skip=1 (which skips the first line) from the second.
The fundamental issue is that batch treats a string of delimiters as a single delimiter, so it's necessary to separate those delimiters. This is not possible against a metavariable, but can be done within a loop by transferring the metavariable into an ordinary environment variable (line) and performing the string-replace ceremony on that ordinary variable in delayed expansion mode.
So - replace each , with |,, then process the resultant string using | as a delimiter. Note that the metavariable is in a different case for the second for - one of the few occasions where cmd is case-sensitive. Reconstruct the string, omitting column 7 (%%G) and using the * token meaning the eighth token (%%H) receives the remainder-of-line after the highest explicitly-mentioned token number (7) and echo it after removing remaining | characters.
Note that it is normal policy to refuse code-requests on SO, and only respond in a manner to fix faulty code. In this case however, succeeding browsers may find this response to be the key to doing a similar task and hence refrain from posting unnecessarily. Also, I'm bored witless.

Windows Batch: replace substring in CSV file

This is a popular subject on the Web but I can't find a simple way to do a find-and-replace inside a CSV file. My CSV file looks like this:
"0.219530613504834,43.7737904197643,PR RUE D'ARTOIS"
"0.522235882011867,41.7681203998576,PR DE LA FOSSE AU ROI"
"0.039404145384227,44.7565229712732,PR DES PETITS PRES"
I need to remove double quotes at the beginning and end of each line.
I tried the following script:
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (D:/data.csv) do (
set temp=%%a
set temp=%temp:^"=%
)
My logic is to store each line in %%a and to replace the double quotes by nothing.
I escape the double quote with ^.
This script is doing nothing. Could you help?
There is a much simpler solution that avoids delayed expansion altogther - The ~ modifier strips enclosing quotes from FOR variable content.
for /f "delims=" %%a in (D:/data.csv) do echo %%~a
Your attempt has several issues:
You need to use delayed expansion (use ! instead of %). Without delayed expansion, the variable gets expanded before the loop is entered.
It's more reliable to use "delims=" than "tokens=*". With "tokens=*" each line is still tokenized, and then all tokens are concatenated separated by a space. But the tokens may have originally been separated by a ;. So if you had "one;two" in the input you'd get "one two" in the output.
You don't need to escape the ".
You need to print temp, not just modify it without using the new value.
setlocal enabledelayedexpansion
for /f "delims=" %%a in (D:/data.csv) do (
set temp=%%a
echo !temp:"=!
)

How to drop all but last cell in CSV using CMD

my goal is to write a script that will monitor process memory usage and run % based comparison on it to determine if there is a memory leak in the said process.
I am using the following command to get the momory usage of the process:
tasklist /fi "imagename eq %PROCESS%" /FO csv | findstr K
SAMPLE:
"cmd.exe","11640","Console","1","3,160 K"
This gives me a CSV file with last cell being the memory usage. I have two problems that I need help with.
Problem 1) How do I drop all but the last cell so that I can then assign the Kb used to a variable for comparison.
Problem 2) How do I get rid of the comma in the number? That kind of makes using comma as delim hard :/
Is there a better command than tasklist for this? I just need the raw number that the program is using, it can be in KB or MB.
Id love to be able to not have dependencies, but if I have to have dependencies I can include them with the batch.
Also is there any way for findstr to not return the entire line?
Thanks for any help! Ive been trying to get this solved for two days now with not much luck.
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%i IN (memcsv.csv) DO CALL :process %%i
GOTO :EOF
:process
SET memsize=%~5
SET memsize=%memsize:,=%
ECHO memsize found = %memsize%
GOTO :eof
This should get your output into a variable called memsize.
It uses a file memcsv.csv as input, but you could replace mmcsv.csv with
'tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem'
to operate directly on the output of FINDSTR. Your resultant line would thus be
FOR /f "delims=" %%i IN ('tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem') DO CALL :process %%i
which, for ease of legibility could be entered as
FOR /f "delims=" %%i IN (
'tasklist /fi "imagename eq %PROCESS%" /FO csv ^| findstr Mem'
) DO CALL :process %%i
Note that the line-breaks are specific - before and after the single-quote.
Also that the single-quotes are REQUIRED and that there is a caret (^) before the pipe (|) which tells cmd that the pipe is part of the command to be executed, not part of the FOR command
Edit to add explanation of HOW.
The ouput of the tasklist...|findstr... can be used as input to a for/f as if it was a file. All you need do is to surround the command with SINGLE-QUOTES and ensure that redirectors like | < > are "escaped" by a caret.
FOR /F "reads" the "file" line-by-line, assigning (by default) the first "token" in the line to the "metavariable" (the loop-control variable, %%i in the above case). This behaviour canbe modified by the addition of control-clauses to the FOR/F. You may use `tokens=x,y,z" for instance to assign token number x, number y and number z to %%i, %%j, %%k respectively.
TOKENS are counted from 1 and have a value of the line contents up to a (series of) delimiter(s). By default, delimiters are spaces, commas, semicolons and TABs, so a line
TOKEN_ONE TOKEN_2,TOKEN_THREE;Token_FOUR
when seen by
for /f "tokens=1,3,4" %%i in (filecontainingaboveline) do
would set %%i=TOKEN_ONE %%j=TOKEN_THREE %%k=Token_FOUR
Using "delims=" turns OFF the delimiters and hence the ENTIRE line is assigned to the metavariable.
HENCE, in the above code, the entire line is assigned to %%i and delivered to the subroutine :process.
From :process's point-of-view, it has been given the argument ** "cmd.exe","11640","Console","1","3,160 K"** which it interprets as a sequence of 5 parameters separated by commas - and a comma (or any other separator) WITHIN "quotes" is data, not a separator.
Parameter number 5 is accessed by %5 - and that is "3,160 K" - including the quotes and comma.
The variable is set to the value of the fifth parameter - the tilde (~) means "remove enclosing quotes." Hence memsize acquires a value of 3,160 K
The next SET replaces the string after the colon in the nominated variable with the string after the = - replace commas with nothing, and assign the result to the memsize variable.
The goto :eof means 'go to the physical end-of-file.` It is very specific - the colon MUST be present. Reaching end-of-file terminates a subroutine or batch-process.
To remove the last 2 characters of the variable, you could use
SET var=%var:0,~-2%
where var is the variable-name.
SEE
SET /?
from the prompt for documentation.
Also GOTO /? and FOR/? for more details on these commands...