【发布时间】:2008-11-24 00:41:18
【问题描述】:
问题说明了一切,我有一个 500,000 行的文件,它是在 Windows 机器上作为自动构建过程的一部分生成的,其中充斥着 ^M 的文件。当它出门时,它需要 *nix 友好,这里最好的方法是什么,是否有一个方便的 sn-p 代码可以为我做到这一点?还是我需要编写一个小 C# 或 Java 应用程序?
【问题讨论】:
标签: windows text-files dos2unix
问题说明了一切,我有一个 500,000 行的文件,它是在 Windows 机器上作为自动构建过程的一部分生成的,其中充斥着 ^M 的文件。当它出门时,它需要 *nix 友好,这里最好的方法是什么,是否有一个方便的 sn-p 代码可以为我做到这一点?还是我需要编写一个小 C# 或 Java 应用程序?
【问题讨论】:
标签: windows text-files dos2unix
这是一个 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
【讨论】:
如果安装基础cygwin 过于繁重,网络上有许多独立的dos2unix 和unix2dos 基于Windows 独立控制台的程序,其中许多都提供C/C++ 源代码。如果我正确理解了需求,那么这些解决方案中的任何一个都可以很好地适应自动构建脚本。
【讨论】:
如果您在 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;
}
【讨论】:
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 框Ftp 到unix 框,作为ascii 文件,而不是二进制文件。 Ftp 会去掉crlf,并插入一个lf。将其作为二进制文件传回dos box,lf会被保留。
【讨论】:
一些文本编辑器,例如UltraEdit/UEStudio 内置了这个功能。
File > Conversions > DOS to UNIX
【讨论】:
not useful for an automated process though = 不正确。 ultraedit/uestudio 都可以从命令行对文件运行宏。它有一个非常强大的脚本引擎,基本上是 javascript,还有一些更强大的方法可用。 ultraedit.com/support/tutorials_power_tips/ultraedit/…
如果只是一个文件,我会使用 notepad++。很好,因为它是免费的。我安装了 cygwin 并使用我为多个文件编写的一个衬里脚本。如果您对脚本感兴趣,请发表评论。 (我暂时没有它。)
【讨论】: