【问题标题】:What's the best way of doing dos2unix on a 500k line file, in Windows? [closed]在 Windows 中,在 500k 行文件上执行 dos2unix 的最佳方法是什么? [关闭]
【发布时间】:2008-11-24 00:41:18
【问题描述】:

问题说明了一切,我有一个 500,000 行的文件,它是在 Windows 机器上作为自动构建过程的一部分生成的,其中充斥着 ^M 的文件。当它出门时,它需要 *nix 友好,这里最好的方法是什么,是否有一个方便的 sn-p 代码可以为我做到这一点?还是我需要编写一个小 C# 或 Java 应用程序?

【问题讨论】:

    标签: windows text-files dos2unix


    【解决方案1】:

    这是一个 Perl 单行代码,取自 http://www.technocage.com/~caskey/dos2unix/

    #!/usr/bin/perl -pi
    s/\r\n/\n/;

    你可以这样运行它:

    perl dos2unix.pl < file.dos > file.unix
    

    或者,您也可以通过这种方式运行它(转换就地完成):

    perl -pi dos2unix.pl file.dos
    

    这是我的(幼稚的)C 版本:

    #include <stdio.h>
    
    int main(void)
    {
       int c;
       while( (c = fgetc(stdin)) != EOF )
          if(c != '\r')
             fputc(c, stdout);
       return 0;
    }
    

    您应该使用输入和输出重定向来运行它:

    dos2unix.exe < file.dos > file.unix
    

    【讨论】:

    • 在必须处理 TB 之前不要担心性能 :D C 版本需要大约 5 秒来转换具有 500000 行文本的 65 MB 文件(在带有标准 EIDE 磁盘的旧 Pentium4 上) )
    • @Federico,(天真的)C 版本将删除所有 CR 字符,而不仅仅是 CR-LF 对中的字符。但我想这就是你称之为天真的原因。 :-)
    【解决方案2】:

    如果安装基础cygwin 过于繁重,网络上有许多独立的dos2unixunix2dos 基于Windows 独立控制台的程序,其中许多都提供C/C++ 源代码。如果我正确理解了需求,那么这些解决方案中的任何一个都可以很好地适应自动构建脚本。

    【讨论】:

      【解决方案3】:

      如果您在 Windows 上并且需要在批处理脚本中运行某些东西,您可以编译一个简单的 C 程序来解决这个问题。

      #include <stdio.h>
      
      int main() {
          while(1) {
              int c = fgetc(stdin);
      
              if(c == EOF)
                  break;
      
              if(c == '\r')
                  continue;
      
              fputc(c, stdout);
          }
      
          return 0;
      }
      

      用法:

      myprogram.exe < input > output
      

      就地编辑会有点困难。此外,您可能出于某种原因想要保留原件的备份(例如,以防您不小心删除了二进制文件)。

      该版本删除了所有个 CR 字符;如果您只想删除 CR-LF 对中的那些,您可以使用(这是经典的单字符返回方法:-):

      /* XXX Contains a bug -- see comments XXX */
      
      #include <stdio.h>
      
      int main() {
          int lastc = EOF;
          int c;
          while ((c = fgetc(stdin)) != EOF) {
              if ((lastc != '\r') || (c != '\n')) {
                  fputc (lastc, stdout);
              }
              lastc = c;
          }
          fputc (lastc, stdout);
          return 0;
      }
      

      您可以使用“r+”模式就地编辑文件。下面是一个通用的 myd2u 程序,它接受文件名作为参数。注意:这个程序使用 ftruncate 在结尾处去掉多余的字符。如果有更好的(标准)方法可以做到这一点,请编辑或评论。谢谢!

      #include <stdio.h>
      
      int main(int argc, char **argv) {
          FILE *file;
      
          if(argc < 2) {
              fprintf(stderr, "Usage: myd2u <files>\n");
              return 1;
          }
      
          file = fopen(argv[1], "rb+");
      
          if(!file) {
              perror("");
              return 2;
          }
      
          long readPos = 0, writePos = 0;
          int lastC = EOF;
      
          while(1) {
              fseek(file, readPos, SEEK_SET);
              int c = fgetc(file);
              readPos = ftell(file);  /* For good measure. */
      
              if(c == EOF)
                  break;
      
              if(c == '\n' && lastC == '\r') {
                  /* Move back so we override the \r with the \n. */
                  --writePos;
              }
      
              fseek(file, writePos, SEEK_SET);
              fputc(c, file);
              writePos = ftell(file);
      
              lastC = c;
          }
      
          ftruncate(fileno(file), writePos); /* Not in C89/C99/ANSI! */
      
          fclose(file);
      
          /* 'cus I'm too lazy to make a loop. */
          if(argc > 2)
              main(argc - 1, argv - 1);
      
          return 0;
      }
      

      【讨论】:

      • @strager,已修复为使用整数(EOF 需要)并添加了仅在 CR-LF 对中执行 CR 的代码 - 希望这会让您获得更多代表。哦,是的,并且投了赞成票。
      • 我注意到使用 int; 的更正;谢谢!我会留下第二个,即使这不是我的风格。 =]
      • 第二个 sn-p 在空文件上失败,尽管修复它相当简单。
      【解决方案4】:
      tr -d '^M' < infile > outfile
      

      您将输入 ^M 为:ctrl+V,回车

      编辑:您可以使用 '\r' 而不是手动输入回车,[感谢@strager]

      tr -d '\r' < infile > outfile
      

      编辑 2:'tr' 是一个 unix 实用程序,您可以从 http://unxutils.sourceforge.net[感谢@Rob Kennedy] 下载本机 Windows 版本或使用 @987654322 @ 的 unix 仿真。

      【讨论】:

      • 如果您在 dos 框上有 tr,这会很好用。它也很快。
      • 我没有tr,在哪里可以找到?
      • 不想为此安装 Cygwin。
      • 本机、非 Cygwin 实用程序:unxutils.sourceforge.net
      • 也可以这样写:tr -d '\r' out
      【解决方案5】:

      将它从dos 框Ftp 到unix 框,作为ascii 文件,而不是二进制文件。 Ftp 会去掉crlf,并插入一个lf。将其作为二进制文件传回dos box,lf会被保留。

      【讨论】:

      • 我不是这个的粉丝,看起来它会是一个 PITA 作为自动构建的一部分。另外,如果我在网络上没有本地 unix 机器,我要么购买一个,要么通过 WAN 传输文件,两次。必须可以在本地执行此操作,不是吗?
      • 我也不是。它至少需要一个正在运行的 FTP 服务器,这对于文件转换来说有点矫枉过正。
      • 虽然很好笑,但答案很好!
      • ASCII 模式下的 FTP 也可以在制表符和空格之间进行转换,具体取决于实现,这是不可取的。
      【解决方案6】:

      一些文本编辑器,例如UltraEdit/UEStudio 内置了这个功能。

      File &gt; Conversions &gt; DOS to UNIX

      【讨论】:

      • gVim 也可以这样做,在 DOS 模式下自动加载它,然后输入 ":set filemode=unix" 不带引号(从内存中)并保存。
      • 虽然对自动化流程没有用处...
      • 啊,真的。 UEStudio 实际上内置了一个相当不错的脚本和宏系统,它实际上可以让您通过命令行执行此操作,但您是对的,它不是自动化流程的最佳工具。
      • not useful for an automated process though = 不正确。 ultraedit/uestudio 都可以从命令行对文件运行宏。它有一个非常强大的脚本引擎,基本上是 javascript,还有一些更强大的方法可用。 ultraedit.com/support/tutorials_power_tips/ultraedit/…
      【解决方案7】:

      如果只是一个文件,我会使用 notepad++。很好,因为它是免费的。我安装了 cygwin 并使用我为多个文件编写的一个衬里脚本。如果您对脚本感兴趣,请发表评论。 (我暂时没有它。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 2014-11-03
        • 1970-01-01
        • 2021-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多