1

First post and apologies in advance for being a complete and utter newb. I have inherited something which I'm just trying to hack a solution for, I have zero knowledge in it. I have searched the forum and believe to have found a part-answer (sed command) however, I'm hitting an issue in getting it to run successfully.

I need for this to run on a Windows box and it was used previous for a simple replace in a .csv file, I now need to insert a header row instead.

I have a 'fixit.cmd' file, which contains this;

set batdir=C:\Sed\filepath\batch
set impdir=C:\Sed\filepath\import
set filename=xxx

:: to read as parameter, uncomment next line
:: set filename=%1

cscript //NoLogo %batdir%\sed.vbs 1i"ABC,123" < %impdir%\%filename%.csv > %impdir%\%filename%_fixed.csv
pause

I have a 'sed.vbs' file, which contains this;

Dim pat, patparts, rxp, inp
pat = WScript.Arguments(0)
patparts = Split(pat,"/")
Set rxp = new RegExp
rxp.Global = True
rxp.Multiline = False
rxp.Pattern = patparts(1)
Do While Not WScript.StdIn.AtEndOfStream
  inp = WScript.StdIn.ReadLine()
  WScript.Echo rxp.Replace(inp, patparts(2))
Loop

When I run the 'fixit.cmd' I receive the error;

sed.vbs(7, 1) Microsoft VBScript runtime error: Subscript out of range: '[number: 1]'

I'm assuming that points towards the 'sed.vbs' content only supportng the previous replace and / or my header row insert string being incorrect.

What amendments do I need to make within the 'sed.vbs' content and / or my header row insert string to successfully insert a header row?

Would really appreciate any / all support.

  • Since you're on Windows, can you use powershell? – Shawn Mar 23 '20 at 13:28
  • I'll eventually have to hand this off so as long as Powershell can be configured in such a way that it can be easily automated and executable via Task Schedule, then, yes, I'm open to explore. – Danny Walker Mar 23 '20 at 14:12
  • Indeed the vb script you found applies a regex on rows, it is not suitable here. If your header does not change then you can simply save it to a separate file and combine it with your csv files using `copy /b header.csv + input.csv input_fixed.csv`. – luciole75w Mar 24 '20 at 07:55
  • As a side note, I would not use the tag "sed" for this question if you actually don't have access to a windows implementation of sed but only to a vb stub ;) – luciole75w Mar 24 '20 at 07:56
  • @luciole75w, appreciate feedback and edits accepted, thanks. I had also read about creating `head.txt` and then `cat head.txt file.csv > newfile.csv`. Header is indeed fixed values. However, and I appreciate I'm asking a lot here, I have no clue how to do that either and would need hand-holding through the exact changes needed to the _'fixit.cmd'_ & _'sed.vbs'_ files I have. Are you able to provide any guidance? – Danny Walker Mar 24 '20 at 09:07

2 Answers2

1

Change your batch file like this:

set "batdir=C:\Sed\filepath\batch"
set "impdir=C:\Sed\filepath\import"
set "filename=xxx"

REM to read as parameter, uncomment next line
REM set filename=%1

>%temp%\header.txt echo ABC,123
copy /b "%temp%\header.txt" + "%impdir%\%filename%.csv" "%impdir%\%filename%_fixed.csv"
pause

The VBS file is not needed anymore.

Some notes on the changes I made:

  • used preferred syntax for the set command (prevents from stray spaces or some special chars
  • The comment command is REM. :: is a malformed label (which works in most cases, but will bite you on some occasions.
  • quotation of paths (preferred syntax to avoid errors with spaces or some special chars in foldernames or filenames)

The line >%temp%\header.txt echo ABC,123 creates a file with the header line.

The copy command concatenates the two files (header and your file),as @luciole75w already wrote in a comment.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • I agree about `rem` vs `::`. Also with the two other remarks about quotes, although it's not my personal preference ;) – luciole75w Mar 24 '20 at 20:03
  • @Stephan - I'm struggling to get this to read in a variable filename from impdir. I have the following, all else remains the same, yet output produced in impdir is simply '_fixed.csv'; set "batdir=C:\Sed\filepath\batch" set "impdir=C:\Sed\filepath\import" set "filename=%1" What am I missing? – Danny Walker Jul 23 '20 at 18:22
  • probably that `%1` is a parameter to the batch file. You have to use it like `mybatch.bat FileName`, so `%1` will be "translated" to `FileName`. Your result shows, that `%1` is empty, that means you didn't give a parameter. – Stephan Jul 23 '20 at 19:53
0

The vbs file is useless here, you can drop it. Your fixit.cmd file could look this :

@echo off

rem  environment variables set after setlocal will be discarded on exit instead
rem  of possibly altering the parent process (optional but good practice)
setlocal

set header_path="C:\Sed\filepath\batch\header.txt"

rem  ~ removes quotes if any, so that input_path is always quoted no matter if
rem  the argument is quoted or not (optional, easier to deal with spaces in paths)
set input_path="%~1"

rem  optional checking
if %input_path%=="" echo missing input file path & exit /b 1

rem  dpn = (d)rive + (p)ath + (n)ame, i.e. full path of input file without extension
set output_path="%~dpn1_fixed.csv"

rem  concatenate header + input to output
copy /b %header_path% + %input_path% %output_path% >nul

This batch file is called with an input csv path as argument (absolute or relative path, extension included). Now if you prefer to generate the header on the fly, then you can replace the last line (copy...) by :

rem  column names including special characters (&, |, < or >) must be quoted
rem  the special character % must be doubled
set header="A|B=>C",50%%

rem  write the header to the output (overwrite the file if it already exists)
rem  parentheses are one way to avoid trailing spaces when redirecting
(echo %header%) > %output_path%

rem  concatenate input to output
type %input_path% >> %output_path%
luciole75w
  • 1,109
  • 6
  • 12
  • Ah, Stephan has been faster :) +1 for all his remarks. Note that he uses another syntax for `set` which is not equivalent to what I used. Both methods are safe but not used the same way. When quoting the whole assignment, the quotes protect the command from special characters in the value then they are discarded, so you have to quote yourself the variable later. When quoting only the right side of `=`, the quotes are part of the variable, so you don't have to quote it everywhere, which can be handy or not, according to what you do after. You choose :) – luciole75w Mar 24 '20 at 20:00
  • You could change `"%~dpn1_fixed.csv"` to `"%~dpn1_fixed%~x1"` to make it more generic. Your quoting is unusual and I find it hard to read, but I guess "personal preference" depends on what you're used to. – Stephan Mar 24 '20 at 22:36
  • @Stephan My quoting may be unusual for you, or yours for me, but honestly I hardly see what is hard to read here. I'd even say that for me it makes the whole batch file easier to read because not scattered with quotes every time the variable is used. Without objective drawbacks in one coding styles or the other, let's respect what we are used to each other :) Cheers. – luciole75w Mar 24 '20 at 23:21
  • Both work equally as well, having tested. Extremely grateful for your inputs. Thank you! – Danny Walker Mar 25 '20 at 09:16
  • @luciole75w: I hate to skim through the whole code to decide if a variable is properly quoted and prefer to see the quotes where they are needed. But as I said, it's a matter of what you are used to. As you said - both methods work and have their individual pros and cons (as long as you consequently use only one of them). – Stephan Mar 25 '20 at 10:04