使用 SED / VBS 将标题行插入 CSV

Posted

技术标签:

【中文标题】使用 SED / VBS 将标题行插入 CSV【英文标题】:Insert Header Row into CSV using SED / VBS 【发布时间】:2020-07-03 21:56:36 【问题描述】:

第一次发帖并提前为自己是一个完整而彻底的新手道歉。我继承了一些我只是想破解解决方案的东西,我对它的了解为零。我已经搜索了论坛并相信已经找到了部分答案(sed 命令)但是,我遇到了让它成功运行的问题。

我需要它在 Windows 机器上运行,它之前用于在 .csv 文件中进行简单的替换,现在我需要插入标题行而是。

我有一个 'fixit.cmd' 文件,其中包含这个;

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

我有一个 'sed.vbs' 文件,其中包含这个;

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

当我运行 'fixit.cmd' 我收到错误消息;

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

我假设指向 的 sed.vbs' 内容仅支持前一个 replace 和/或我的标题行插入字符串不正确。

我需要在 'sed.vbs' 内容和/或我的标题行插入字符串中进行哪些修改才能成功插入标题行

非常感谢任何/所有支持。

【问题讨论】:

既然你在Windows上,你能用powershell吗? 我最终将不得不放弃这个,只要 Powershell 可以配置为可以通过任务计划轻松自动化和执行,那么,是的,我愿意探索。 确实,您发现的 vb 脚本在行上应用了正则表达式,这里不适合。如果您的标题没有更改,那么您可以简单地将其保存到一个单独的文件中,然后使用copy /b header.csv + input.csv input_fixed.csv 将其与您的 csv 文件合并。 附带说明,如果您实际上无权访问 sed 的 Windows 实现,而只能访问 vb 存根,我不会使用标签“sed”来回答这个问题;) @luciole75w,感谢您接受反馈和编辑,谢谢。我还阅读了有关创建head.txtcat head.txt file.csv &gt; newfile.csv 的信息。标头确实是固定值。但是,我很感激我在这里问了很多,我也不知道如何做到这一点,并且需要通过 'fixit.cmd''sed.vbs' 文件。你能提供任何指导吗? 【参考方案1】:

vbs文件在这里没用,你可以把它扔掉。您的 fixit.cmd 文件可能如下所示:

@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

此批处理文件以输入 csv 路径作为参数调用(绝对或相对路径,包括扩展名)。现在,如果您更喜欢动态生成标题,那么您可以将最后一行 (copy...) 替换为:

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%

【讨论】:

啊,Stephan 更快了 :) 为他的所有评论 +1。请注意,他对set 使用了另一种语法,这与我使用的不同。两种方法都是安全的,但使用方式不同。引用整个赋值时,引号会保护命令免受值中的特殊字符的影响,然后它们会被丢弃,因此您必须稍后自己引用变量。当只引用=的右侧时,引号是变量的一部分,所以你不必到处引用它,这是否方便,取决于你之后做什么。你选择:) 您可以将"%~dpn1_fixed.csv" 更改为"%~dpn1_fixed%~x1" 以使其更通用。您的引用很不寻常,我觉得很难阅读,但我想“个人偏好”取决于您的习惯。 @Stephan 我的引述对你来说可能是不寻常的,或者对我来说可能是不寻常的,但老实说,我几乎看不出这里有什么难以阅读的地方。我什至会说,对我来说,它使整个批处理文件更易于阅读,因为每次使用变量时都不会分散在引号中。在一种编码风格或另一种编码风格没有客观缺陷的情况下,让我们尊重我们彼此习惯的东西:) 干杯。 经过测试,两者同样有效。非常感谢您的投入。谢谢! @luciole75w:我讨厌浏览整个代码来确定变量是否被正确引用,并且更喜欢在需要它们的地方查看引号。但正如我所说,这是你习惯的问题。正如您所说 - 这两种方法都有效并且各有利弊(只要您因此只使用其中一种)。【参考方案2】:

像这样更改您的批处理文件:

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

不再需要 VBS 文件。

关于我所做更改的一些注释:

使用set 命令的首选语法(防止出现杂散空格或某些特殊字符 评论命令是REM:: 是一个格式错误的标签(在大多数情况下有效,但在某些情况下会咬你。 引用路径(首选语法以避免文件夹名或文件名中出现空格或某些特殊字符错误)

&gt;%temp%\header.txt echo ABC,123 行创建带有标题行的文件。

copy 命令连接两个文件(头文件和您的文件),正如@luciole75w 已在评论中所写。

【讨论】:

我同意 rem::。还有另外两个关于引号的评论,虽然这不是我个人的偏好;) @Stephan - 我正在努力让它从 impdir 读取变量文件名。我有以下内容,其他一切都保持不变,但 impdir 中产生的输出只是 '_fixed.csv'; set "batdir=C:\Sed\filepath\batch" set "impdir=C:\Sed\filepath\import" set "filename=%1" 我错过了什么? 可能%1 是批处理文件的参数。你必须像mybatch.bat FileName 一样使用它,所以%1 将被“翻译”成FileName。您的结果显示,%1 为空,这意味着您没有提供参数。

以上是关于使用 SED / VBS 将标题行插入 CSV的主要内容,如果未能解决你的问题,请参考以下文章

使用 sed 在匹配后插入行

sed 插入行命令 OSX

sed / awk - 使用模式匹配后插入空格

VBS怎么往CSV文件中写数据

gnu parallel + sed 编辑 csv 标题和内容

使用 vba 将 xls/csv 文件插入到 access 2007 表中