草庐IT

windows - Windows批处理脚本以解析CSV文件并输出文本文件

coder 2023-11-10 原文

我在另一页(Help in writing a batch script to parse CSV file and output a text file)上看到了响应-出色的代码BTW:

@ECHO OFF
IF "%~1"=="" GOTO :EOF
SET "filename=%~1"
SET fcount=0
SET linenum=0
FOR /F "usebackq tokens=1-10 delims=," %%a IN ("%filename%") DO ^
CALL :process "%%a" "%%b" "%%c" "%%d" "%%e" "%%f" "%%g" "%%h" "%%i" "%%j"
GOTO :EOF

:trim
SET "tmp=%~1"
:trimlead
IF NOT "%tmp:~0,1%"==" " GOTO :EOF
SET "tmp=%tmp:~1%"
GOTO trimlead

:process
SET /A linenum+=1
IF "%linenum%"=="1" GOTO picknames

SET ind=0
:display
IF "%fcount%"=="%ind%" (ECHO.&GOTO :EOF)
SET /A ind+=1
CALL :trim %1
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO !f%ind%!!tmp!
ENDLOCAL
SHIFT
GOTO display

:picknames
IF %1=="" GOTO :EOF
CALL :trim %1
SET /a fcount+=1
SET "f%fcount%=%tmp%"
SHIFT
GOTO picknames

它对于以下格式的示例csv文件非常有用:
Header,Name,Place
one,two,three
four,five,six

但是,我要更改的实际文件包含64个字段-因此我将tokens=1-10更改为tokens=1-64,并增加了%%a等,最多可包含64个变量(例如,最后一个称为%%BL)。但是,现在,当我在“大” csv文件(带有64个 token )上运行批处理时,什么也没发生。没有错误(良好),但没有输出! (坏的)。如果有人可以帮忙,那真是太棒了……如果我能确定这最后一点,我将使整个应用程序正常工作!或者,如果有人有一些示例代码将对无限数量的标记执行类似的操作……最终,我想制作一个类似于以下内容的字符串:
field7,field12,field15,field18

最佳答案

重要更新-我认为Windows批处理不是满足您需求的好选择,因为单个FOR/F不能解析超过31个 token 。有关说明,请参见下面的附录底部。

但是,可以批量处理所需的操作。这个丑陋的代码将使您能够访问所有64个 token 。

for /f "usebackq tokens=1-29* delims=," %%A in ("%filename%") do (
  for /f "tokens=1-26* delims=," %%a in ("%%^") do (
    for /f "tokens=1-9 delims=," %%1 in ("%%{") do (
      rem Tokens 1-26 are in variables %%A - %%Z
      rem Token  27 is in %%[
      rem Token  28 is in %%\
      rem Token  29 is in %%]
      rem Tokens 30-55 are in %%a - %%z
      rem Tokens 56-64 are in %%1 - %%9
    )
  )
)

附录提供了有关上述工作原理的重要信息。

如果您只需要在行中的64个 token 中散布一些 token ,那么该解决方案将稍微容易一些,因为您可以避免使用疯狂的字符作为FOR变量。但是,仍然需要仔细进行簿记。

例如,以下内容将使您可以访问 token 5、27、46和64
for /f "usebackq tokens=5,27,30* delims=," %%A in ("%filename%") do (
  for /f "tokens=16,30* delims=," %%E in ("%%D") do (
    for /f "tokens=4 delims=," %%H in ("%%G") do (
      rem Token  5 is in %%A
      rem Token 27 is in %%B
      rem Token 46 is in %%E
      rem Token 64 is in %%H
    )
  )
)

2016年4月更新-基于DosTips用户Aacini,penpen和aGerman的调查工作,我开发了一种相对简单的方法,可以使用FOR/F同时访问数千个 token 。该作品是this DosTips thread的一部分。实际的代码可以在以下3个帖子中找到:
  • Work with a fixed number of columns
  • Work with varying numbers of columns
  • Dynamically choose which tokens to expand within the DO clause

  • 原始答案
    FOR变量限制为单个字符,因此您的%% BL策略无法正常工作。变量区分大小写。根据Microsoft的说法,您只能在一个FOR语句中捕获26个 token ,但是如果您使用的不只是alpha,则有可能获得更多。这很麻烦,因为您需要一个ASCII表来确定哪些字符在哪里。但是,FOR不允许仅使用任何字符,并且单个FOR/F可以分配的最大 token 数为31 +1。正如您所发现的那样,任何尝试分析和分配31个以上的尝试都将悄然失败。

    值得庆幸的是,我认为您不需要那么多 token 。您只需使用“ token ”选项指定所需的 token 。
    for /f "usebackq tokens=7,12,15,18 delims=," %%A in ("%filename%") do echo %%A,%%B,%%C,%%D
    

    将为您提供第7、12、15和18个 token 。

    附录

    ,2016年4月更新,几周前,我了解到以下规则(6年前编写)取决于代码页。已针对代码页437和850验证了以下数据。更重要的是,扩展ASCII字符128-254的FOR变量序列与字节代码值不匹配,并且因代码页而异。事实证明,FOR/F变量映射基于基础UTF-(16?)代码点。因此,与FOR/F一起使用时,扩展的ASCII字符的使用受到限制。有关更多信息,请参见http://www.dostips.com/forum/viewtopic.php?f=3&t=7703上的线程。

    我进行了一些测试,并且可以报告以下内容(根据jeb的评论进行了更新):

    大多数字符都可以用作FOR变量,包括扩展的ASCII 128-254。但是某些字符不能用于在FOR语句的第一部分中定义变量,而可以在DO子句中使用。几个都不能使用。有些没有限制,但是需要特殊的语法。

    以下是有限制或需要特殊语法的字符的摘要。请注意,尖括号内的文本(例如<space>)表示单个字符。
    Dec  Hex   Character   Define     Access
      0  0x00  <nul>       No         No
     09  0x09  <tab>       No         %%^<tab>  or  "%%<tab>"
     10  0x0A  <LF>        No         %%^<CR><LF><CR><LF>  or  %%^<LF><LF>
     11  0x0B  <VT>        No         %%<VT>
     12  0x0C  <FF>        No         %%<FF>
     13  0x0D  <CR>        No         No
     26  0x1A  <SUB>       %%%VAR%    %%%VAR% (%VAR% must be defined as <SUB>)
     32  0x20  <space>     No         %%^<space>  or  "%%<space>"
     34  0x22  "           %%^"       %%"  or  %%^"
     36  0x24  $           %%$        %%$ works, but %%~$ does not
     37  0x25  %           %%%%       %%~%%
     38  0x26  &           %%^&       %%^&  or  "%%&"
     41  0x29  )           %%^)       %%^)  or  "%%)"
     44  0x2C  ,           No         %%^,  or  "%%,"
     59  0x3B  ;           No         %%^;  or  "%%;"
     60  0x3C  <           %%^<       %%^<  or  "%%<"
     61  0x3D  =           No         %%^=  or  "%%="
     62  0x3E  >           %%^>       %%^>  or  "%%>"
     94  0x5E  ^           %%^^       %%^^  or  "%%^"
    124  0x7C  |           %%^|       %%^|  or  "%%|"
    126  0x7E  ~           %%~        %%~~ (%%~ may crash CMD.EXE if at end of line)
    255  0xFF  <NB space>  No         No
    

    特殊字符(例如^ < > | &)必须转义或加引号。例如,以下工作:
    for /f %%^< in ("OK") do echo "%%<" %%^<
    

    某些字符不能用于定义FOR变量。例如,以下给出了语法错误:
    for /f %%^= in ("No can do") do echo anything
    

    但是可以使用TOKENS选项隐式定义%%=,并在DO子句中访问该值,如下所示:
    for /f "tokens=1-3" %%^< in ("A B C") do echo %%^< %%^= %%^>
    
    %是奇数-您可以使用%%%%定义一个FOR变量。但是,除非使用~修饰符,否则无法访问该值。这意味着不能保留引号。
    for /f "usebackq tokens=1,2" %%%% in ('"A"') do echo %%%% %%~%%
    

    上面产生%% A~是潜在危险的FOR变量。如果尝试在行尾使用%%~访问变量,则可能会得到无法预料的结果,甚至可能使CMD.EXE崩溃!不受限制地访问它的唯一可靠方法是使用%%~~,它当然会去除所有封闭的引号。
    for /f %%~ in ("A") do echo This can crash because its the end of line: %%~
    
    for /f %%~ in ("A") do echo But this (%%~) should be safe
    
    for /f %%~ in ("A") do echo This works even at end of line: %%~~
    
    <SUB>(0x1A)字符是特殊字符,因为批处理脚本中嵌入的<SUB>文字被读取为换行符(<LF>)。为了将<SUB>用作FOR变量,必须以某种方式将值存储在环境变量中,然后%%%VAR%将同时用于定义和访问。

    如前所述,单个FOR/F可以解析和分配最多31个 token 。例如:
    @echo off
    setlocal enableDelayedExpansion
    set "str="
    for /l %%n in (1 1 35) do set "str=!str! %%n"
    for /f "tokens=1-31" %%A in ("!str!") do echo A=%%A _=%%_
    

    上面产生A=1 _=31注意- token 2-30正常工作,我只想举一个小例子

    如果不设置ERRORLEVEL,则任何试图解析和分配31个以上 token 的尝试都将无提示地失败。
    @echo off
    setlocal enableDelayedExpansion
    set "str="
    for /l %%n in (1 1 35) do set "str=!str! %%n"
    for /f "tokens=1-32" %%A in ("!str!") do echo this example fails entirely
    

    您最多可以解析并分配31个 token ,然后将其余 token 分配给另一个 token ,如下所示:
    @echo off
    setlocal enableDelayedExpansion
    set "str="
    for /l %%0 in (1 1 35) do set "str=!str! %%n"
    for /f "tokens=1-31*" %%@ in ("!str!") do echo @=%%A  ^^=%%^^  _=%%_
    

    上面产生@=1 ^=31 _=32 33 34 35
    现在是真正的坏消息。 正如我在查看Number of tokens limit in a FOR command in a Windows batch script时所了解的那样,单个FOR/F永远不能解析超过31个 token
    @echo off
    setlocal enableDelayedExpansion
    set "str="
    for /l %%n in (1 1 35) do set "str=!str! %%n"
    for /f "tokens=1,31,32" %%A in ("!str!") do echo A=%%A  B=%%B  C=%%C
    

    非常不幸的输出是A=1 B=31 C=%C

    关于windows - Windows批处理脚本以解析CSV文件并输出文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8520313/

    有关windows - Windows批处理脚本以解析CSV文件并输出文本文件的更多相关文章

    1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

      我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

    2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

      我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

    3. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    4. ruby - 用逗号、双引号和编码解析 csv - 2

      我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

    5. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

      查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

    6. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

      我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

    7. ruby CSV : How can I read a tab-delimited file? - 2

      CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

    8. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

      这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

    9. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

      之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

    10. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

      //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

    随机推荐