如何在Unix行尾(CR / LF到LF)中转换Windows行尾


79

我是Java开发人员,正在使用Ubuntu进行开发。该项目是使用Eclipse在Windows中创建的,并且使用Windows-1252编码。

要转换为UTF-8,我使用了重新编码程序:

find Web -iname \*.java | xargs recode CP1252...UTF-8

此命令给出此错误:

recode: Web/src/br/cits/projeto/geral/presentation/GravacaoMessageHelper.java failed: Ambiguous output in step `CR-LF..data

我已经搜索了它,并在Bash和Windows中获得了解决方案,重新编码:在“ data..CR-LF”步骤中的输出模棱两可,它说:

将行尾从CR / LF转换为单个LF:使用Vim编辑文件,输入命令:set ff=unix并保存文件。现在重新编码应该可以正常运行。

很好,但是我有很多文件要从中删除CR / LF字符,我无法打开每个文件来完成。Vi不为Bash操作提供任何命令行选项。

sed可以用来做到这一点吗?怎么样?


recode尝试使用Dos(\r\n-CRLF)和UNIX(\nLF)换行符混合编码重新编码文件时,会产生此错误。不幸的是fromdos,以前是二进制文件,当前是要重新编码的别名,因此存在此问题。
TMS

你不能吗vim +ex_command_one +ex_command_two ... file
derekdreery '16

惊人!awk答案中没有解决方案。
Gerold Broser

Answers:


121

应该有一个名为的程序dos2unix,它将为您修复行尾。如果您的Linux机器上尚未安装它,则应该可以通过软件包管理器使用它。


2
我安装了提供fromdos命令的tofrodos,但是问题仍然存在。fromdos -a GravacaoMessageHelper.java; 重新编码CP1252 ... UTF-8 GravacaoMessageHelper.java返回:重新编码:GravacaoMessageHelper.java失败:步骤“ CR-LF..data”中的输出不明确
MaikoID 2010年

1
@MaikoID:那你有更大的问题。无论如何,recode都不在乎行尾,因为CR只是要转换的另一个字符。而且似乎不在乎我的机器。
cHao 2010年

1
fromdos只是的别名recode,将产生混合dos(\ r \ n-CRLF)和unix(\ n LF)编码的文件中提到的错误OP。仅dos2unix通用。
TMS

1
dos2unix可通过自制软件在OS X上使用:“ brew install dos2unix”
Joseph Sheedy

1
只是为了跟进此,我遇到了同样的问题,并最终使用的情况如下:find ./ -name "*.java" -exec dos2unix {} +
amracel

84

sed无法匹配\ n,因为尾随换行符是在将行放入模式空间之前删除的,但是可以匹配\ r,因此您可以通过删除\ r将\ r \ n(dos)转换为\ n(unix)

sed -i 's/\r//g' file

警告:这将更改原始文件

但是,您不能由此从unix EOL更改为dos或旧的mac(\ r)。在这里更多阅读:

如何使用sed替换换行符(\ n)?


4
+1这是一个不错的解决方案!但是您应该注意,这sed -i将更改原始文件!因为人们不会期望sed这样做,所以在这里警告是适当的。没有多少人知道,-i所以他们会尝试sed -i ... file > file2并且不希望原始文件被修改。
TMS

并非所有sed变体都能识别非标准符号序列\r。在这种情况下,请尝试使用文字ctrl-M字符(在许多shell中,键入ctrl-V ctrl-M即可产生文字控制字符)。
点钟

14

实际上,vim确实可以满足您的需求。输入vim,然后键入以下命令:

:args **/*.java
:argdo set ff=unix | update | next

这些命令中的第一个命令将参数列表**/*.java递归设置到每个匹配的文件(即所有Java文件)中。这些命令的第二个依次对参数列表中的每个文件执行以下操作:

  • 将行尾设置为Unix风格(您已经知道了)
  • 如果文件已更改,则将其写出
  • 前进到下一个文件

这可能比dos2unix在for循环中使用要慢得多,但是知道如何在Vim中进行操作仍然很高兴!
jpaugh

2
我::心::我的vim。这次真是万分感谢。
乔诺,2016年

8

tr命令也可以这样做:

tr -d '\15\32' < winfile.txt > unixfile.txt

并且应该对您可用。

您需要在脚本中运行tr,因为它无法使用文件名。例如,创建一个文件myscript.sh:

#!/bin/bash

for f in `find -iname \*.java`; do
    echo "$f"
    tr -d '\15\32' < "$f" > "$f.tr"
    mv "$f.tr" "$f"
    recode CP1252...UTF-8 "$f"
done

运行myscript.sh将处理当前目录及其子目录中的所有java文件。


如何适应查找Web -iname * .java | xargs重新编码CP1252 ... UTF-8
MaikoID 2010年

您将需要在bash脚本中运行tr,因为它不适用于文件名。我将使用示例脚本编辑答案。
KeithL 2010年

Thnx的答案,但错误仍然存​​在= | 步骤“ CR-LF..data”中的输出不明确
MaikoID 2010年

7

我会略去吉超的回答。实际上,您可以轻松地完成他刚刚谈到的所有事情。而不是寻找\n,只需寻找行尾的回车即可。

sed -i 's/\r$//' "${FILE_NAME}"

要从Unix更改为dos,只需查找该行的最后一个字符并向其中添加换页。(我将添加-r使用grep正则表达式使此操作更容易。)

sed -ri 's/(.)$/\1\r/' "${FILE_NAME}"

从理论上讲,可以通过将代码添加到最后一个示例中来将文件更改为mac样式,该示例还将下一行输入追加到第一行,直到处理完所有行。不过,我不会在这里举这个例子。

警告: -i更改实际文件。如果要进行备份,请在之后添加一个字符串-i。这会将现有文件移动到与您的字符添加到最后的同名文件。


1
我喜欢您的建议,但它只是缺少一个结尾的单引号。它应该是:sed
-ri's /(。)$

1
@mgouin感谢您的注意。我添加了缺少的单引号。
John Chesshir

1
要将LF转换为CRLF,不需要捕获行尾的最后一个字符,这也可能影响性能。就我而言,这足以做sed -i 's/$/\r/' ${FILE_NAME}...
托马斯·厄本

-r选项不可移植;如果您sed没有,请尝试-E
三点

5

为了克服

Ambiguous output in step `CR-LF..data'

简单的解决方案可能是添加-f标志以强制转换。


0

您是否尝试过在这里找到的Bryan Maupinpython脚本?(我对其进行了一些修改,以使其更通用)

#!/usr/bin/env python

import sys

input_file_name = sys.argv[1]
output_file_name = sys.argv[2]

input_file = open(input_file_name)
output_file = open(output_file_name, 'w')

line_number = 0

for input_line in input_file:
    line_number += 1
    try:  # first try to decode it using cp1252 (Windows, Western Europe)
        output_line = input_line.decode('cp1252').encode('utf8')
    except UnicodeDecodeError, error:  # if there's an error
        sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
        try:  # then if that fails, try to decode using latin1 (ISO 8859-1)         
            output_line = input_line.decode('latin1').encode('utf8')
        except UnicodeDecodeError, error:  # if there's an error
            sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
            sys.exit(1)  # and just keep going
    output_file.write(output_line)

input_file.close()
output_file.close()

您可以将该脚本与

$ ./cp1252_utf8.py file_cp1252.sql file_utf8.sql

-1

返回Windows,告诉Eclipse将编码更改为UTF-8,然后返回Unix并d2u在文件上运行。


尽管文件很多,但这可能比您愿意投入的工作还要多...
Jonathan 2010年

什么是d2u?在哪里找到它?
JesperRønn-Jensen2011年

它偶尔会被重命名。看起来Ubuntufromdos在10.04中称它,它是该软件包的一部分tofrodos
乔纳森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.