\r
从 Unix 文件中删除所有回车的最简单方法是什么?
21 回答
我将假设您的意思是在行尾的回车(,CR , "\r"
)0x0d
,而不是盲目地在文件中(据我所知,您可能将它们放在字符串的中间)。仅在第一行末尾使用此测试文件:CR
$ cat infile
hello
goodbye
$ cat infile | od -c
0000000 h e l l o \r \n g o o d b y e \n
0000017
dos2unix
如果它已安装在您的系统上,这是要走的路:
$ cat infile | dos2unix -U | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
如果由于某种原因dos2unix
您无法使用,那么sed
将这样做:
$ cat infile | sed 's/\r$//' | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
如果由于某种原因sed
您无法使用,那么ed
将以一种复杂的方式进行操作:
$ echo ',s/\r\n/\n/
> w !cat
> Q' | ed infile 2>/dev/null | od -c
0000000 h e l l o \n g o o d b y e \n
0000016
如果您的盒子上没有安装任何这些工具,那么您遇到的问题比尝试转换文件要大:-)
tr -d '\r' < infile > outfile
在我看来,Linux 上最简单的方法是,
sed -i.bak 's/\r$//g' <filename>
-i将就地编辑文件,而.bak将通过制作文件副本并在末尾添加扩展名.bak来创建原始文件的备份。(您可以在 之后指定您想要的任何内容-i
,或仅指定-i
不创建备份。)
替换运算符周围的强引号's/\r//'
是必不可少的。没有它们,shell 将解释\r
为 escape+r 并将其简化为 plain r
,并删除所有小写字母r
。这就是Rob在 2009 年上面给出的答案不起作用的原因。
添加/g
修饰符可确保\r
删除多个,而不仅仅是第一个。
老套:
tr -d '\r' < filewithcarriagereturns > filewithoutcarriagereturns
许多系统上都有一个名为dos2unix的实用程序,并且可以在大多数系统上轻松安装。
sed -i s/\r// <filename>
或类似的东西;请参阅man sed
或在网络上提供有关使用sed
.
需要指出的一点是上面“回车”的确切含义;如果您真正的意思是单个控制字符“回车”,那么上面的模式是正确的。如果您的意思是,更一般地说,CRLF(回车和换行,这是在 Windows 下实现换行的方式),那么您可能想要替换\r\n
。Linux/Unix 中的裸换行符(换行符)是\n
.
如果您是 Vi 用户,您可以使用以下命令打开文件并删除回车:
:%s/\r//g
或与
:1,$ s/^M//
请注意,您应该通过按 ctrl-v 然后按 ctrl-m 来输入 ^M。
又是一个解决方案……因为总会有一个解决方案:
perl -i -pe 's/\r//' filename
这很好,因为它已经到位并且适用于我使用过的各种 unix/linux。
其他人推荐dos2unix
,我也强烈推荐。我只是提供更多细节。
如果已安装,请跳至下一步。如果尚未安装,我建议通过以下方式安装它yum
:
yum install dos2unix
然后你可以像这样使用它:
dos2unix fileIWantToRemoveWindowsReturnsFrom.txt
\r
在任何 UNIX® 系统上删除:
这个问题中的大多数现有解决方案都是特定于 GNU 的,并且不适用于 OS X 或 BSD;下面的解决方案应该可以在更多的 UNIX 系统上工作,并且在任何 shell 中,从tcsh
to sh
,但即使在 GNU/Linux 上也仍然可以工作。
在 OS X、OpenBSD 和 NetBSD 上测试tcsh
,在 Debian GNU/Linux 上测试bash
。
与sed
:
在tcsh
OS X 上,以下sed
代码段可以与 一起使用printf
,因为它既不sed
也不会像 GNU 那样以特殊方式echo
处理:\r
sed `printf 's/\r$//g'` input > output
与tr
:
另一种选择是tr
:
tr -d '\r' < input > output
sed
和之间的区别tr
:
似乎tr
保留了输入文件中缺少尾随换行符的情况,而sed
在 OS X 和 NetBSD(但不是在 OpenBSD 或 GNU/Linux 上)即使输入缺少任何内容,也会在文件的最后插入尾随换行符在文件的末尾\r
或\n
末尾。
测试:
以下是一些示例测试,可用于确保它在您的系统上运行,使用printf
and hexdump -C
; 或者,od -c
如果您的系统丢失,也可以使用hexdump
:
% printf 'a\r\nb\r\nc' | hexdump -C
00000000 61 0d 0a 62 0d 0a 63 |a..b..c|
00000007
% printf 'a\r\nb\r\nc' | ( sed `printf 's/\r$//g'` /dev/stdin > /dev/stdout ) | hexdump -C
00000000 61 0a 62 0a 63 0a |a.b.c.|
00000006
% printf 'a\r\nb\r\nc' | ( tr -d '\r' < /dev/stdin > /dev/stdout ) | hexdump -C
00000000 61 0a 62 0a 63 |a.b.c|
00000005
%
如果您使用的操作系统(如 OS X)没有该dos2unix
命令但有 Python 解释器(版本 2.5+),则此命令等效于以下dos2unix
命令:
python -c "import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))"
这处理命令行上的命名文件以及管道和重定向,就像dos2unix
. 如果将此行添加到 ~/.bashrc 文件(或其他 shell 的等效配置文件):
alias dos2unix="python -c \"import sys; import fileinput; sys.stdout.writelines(line.replace('\r', '\n') for line in fileinput.input(mode='rU'))\""
...下次您登录(或source ~/.bashrc
在当前会话中运行)时,您将能够以dos2unix
与其他示例相同的方式在命令行上使用该名称。
你可以简单地这样做:
$ echo $(cat input) > output
事情是这样的,
%0d
是回车符。使其与 Unix 兼容。我们需要使用下面的命令。
dos2unix fileName.extension fileName.extension
试试这个将dos文件转换成unix文件:
从dos文件
对于 UNIX... 我注意到 dos2unix 从我的 UTF-8 文件中删除了 Unicode 标头。在 git bash (Windows) 下,以下脚本似乎运行良好。它使用 sed。请注意,它仅删除行尾的回车符,并保留 Unicode 标头。
#!/bin/bash
inOutFile="$1"
backupFile="${inOutFile}~"
mv --verbose "$inOutFile" "$backupFile"
sed -e 's/\015$//g' <"$backupFile" >"$inOutFile"
如果您正在运行 X 环境并拥有适当的编辑器(Visual Studio 代码),那么我将遵循建议:
只需转到屏幕的右下角,Visual Studio 代码就会向您显示文件编码和文件后跟的行尾约定,只需单击一下即可切换。
只需在 linux 环境中使用可视代码作为 notepad++ 的替代品,您就可以开始使用了。
cat input.csv | sed 's/\r/\n/g' > output.csv
为我工作
使用sed
sed $'s/\r//' infile > outfile
sed
在 Windows 版 Git Bash 上使用
sed '' infile > outfile
第一个版本使用ANSI-C 引用\
,如果命令从脚本运行,可能需要转义。第二个版本利用了通过删除和字符sed
逐行读取输入文件的事实。但是,在将行写入输出文件时,它只附加一个字符。只需修改即可设计出更通用和跨平台的解决方案\r
\n
\n
IFS
IFS=$'\r\n' # or IFS+=$'\r' if the lines do not contain whitespace
printf "%s\n" $(cat infile) > outfile
IFS=$' \t\n' # not necessary if IFS+=$'\r' is used
警告:此解决方案执行文件名扩展(如果设置了*
,?
和[...]
更多)。extglob
仅当您确定文件不包含特殊字符或您想要扩展时才使用它。
警告:没有一个解决方案可以\
在输入文件中处理。
我用过python,这里是我的代码;
end1='/home/.../file1.txt'
end2='/home/.../file2.txt'
with open(end1, "rb") as inf:
with open(end2, "w") as fixed:
for line in inf:
line = line.replace("\n", "")
line = line.replace("\r", "")
fixed.write(line)
虽然这是一个较旧的帖子,但最近我遇到了同样的问题。由于我在 /tmp/blah_dir/ 中要重命名所有文件,因为该目录中的每个文件都有“/r”尾随字符(在文件末尾显示“?”),所以只有我能想到的脚本方式。
我想用相同的名称保存最终文件(不带任何字符)。使用 sed,问题是输出文件名,我需要提及其他内容(我不想要)。
我尝试了这里建议的其他选项(由于某些限制,不考虑 dos2unix)但没有奏效。
我最终尝试了“awk”,它在我使用“\r”作为分隔符并采用第一部分的情况下工作:
诀窍是:
echo ${filename}|awk -F"\r" '{print $1}'
下面我使用的脚本片段(我所有文件在路径/tmp/blah_dir/处都有“\r”作为尾随字符)来解决我的问题:
cd /tmp/blah_dir/
for i in `ls`
do
mv $i $(echo $i | awk -F"\r" '{print $1}')
done
注意:这个例子虽然与我的工作很接近,但并不是很准确(在这里提及只是为了更好地了解我所做的事情)
我制作了这个 shell 脚本来删除 \r 字符。它适用于 solaris 和 red-hat:
#!/bin/ksh
LOCALPATH=/Any_PATH
for File in `ls ${LOCALPATH}`
do
ARCACT=${LOCALPATH}/${File}
od -bc ${ARCACT}|sed -n 'p;n'|sed 's/015/012/g'|awk '{$1=""; print $0}'|sed 's/ /\\/g'|awk '{printf $0;}'>${ARCACT}.TMP
printf "`cat ${ARCACT}.TMP`"|sed '/^$/d'>${ARCACT}
rm ${ARCACT}.TMP
done
exit 0