在Unix中从文件中删除所有回车\r的最简单方法是什么?
Sed -i s/\r// <文件名>或someesuch;请参阅man sed或web上有关sed使用的丰富信息。
有一点需要指出的是上面“马车返回”的确切含义;如果您真正指的是单个控制字符“回车”,那么上面的模式是正确的。如果您指的是更一般的CRLF(回车和换行,这是Windows下换行的实现方式),那么您可能希望替换\r\n。Linux/Unix中的换行符(换行符)是\n。
我将假设您是指行尾的回车符(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
如果你没有在你的盒子上安装任何这些工具,你有比试图转换文件更大的问题:-)
如果你使用的操作系统(如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 ~/.)您将能够在命令行上以与其他示例相同的方式使用dos2unix名称。
有人推荐dos2unix,我也强烈推荐。我只是提供更多的细节。
如果已安装,请跳转到下一步。如果还没有安装,我建议通过yum安装:
yum install dos2unix
然后你可以这样使用它:
dos2unix fileIWantToRemoveWindowsReturnsFrom.txt
事情是这样的,
%0d是回车字符。使它与Unix兼容。我们需要使用下面的命令。
dos2unix fileName。extension fileName.extension
这又是一个解决方案……因为总还有一个问题:
perl -i -pe 's/\r//' filename
它很好,因为它可以在我使用过的所有unix/linux版本中工作。
我用的是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)
在我看来,Linux上最简单的方法是,
sed -i.bak 's/\r$//g' <filename>
-i将编辑文件,而.bak将创建原始文件的备份,复制您的文件并在末尾添加扩展名.bak。(你可以在-i后面指定任何你想要的,或者只指定-i来不创建备份。)
替换操作符's/\r//'周围的强引号是必不可少的。如果没有它们,shell将把\r解释为转义+r,并将其简化为纯r,并删除所有小写r。这就是为什么Rob在2009年给出的答案不起作用。
添加/g修饰符可以确保即使是多个\r也会被删除,而不仅仅是第一个\r。
对于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代码:如何显示行结束
只要转到屏幕的右下角,visual studio代码就会显示文件编码和文件后面的行结束约定,只需简单地单击就可以切换。
只要在linux环境下使用可视化代码作为notepad++的替代品,你就可以开始了。
虽然这是一篇较老的文章,但最近我遇到了同样的问题。因为我有所有的文件重命名/tmp/blah_dir/,因为这个目录中的每个文件都有“/r”结尾字符(在文件末尾显示“?”),所以做脚本的方式是我唯一能想到的。
我想保存具有相同名称的最终文件(不拖尾任何字符)。 对于sed,问题是输出文件名,我需要提到其他东西(我不想要)。
我尝试了这里建议的其他选项(由于某些限制,不考虑dos2unix),但没有成功。
我尝试了“awk”,最后我使用“\r”作为分隔符,并采取了第一部分:
技巧是:
echo ${filename}|awk -F"\r" '{print $1}'
下面的脚本片段我用(我有所有文件有“\r”作为结尾字符在路径/tmp/blah_dir/)来解决我的问题:
cd /tmp/blah_dir/
for i in `ls`
do
mv $i $(echo $i | awk -F"\r" '{print $1}')
done
注:这个例子不是很精确,但接近我的工作(这里提到只是为了更好地了解我所做的工作)
在任何UNIX®系统上删除\r:
这个问题中的大多数现有解决方案都是特定于gnu的,在OS X或BSD上不起作用;下面的解决方案可以在更多的UNIX系统上工作,也可以在从tcsh到sh的任何shell中工作,甚至还可以在GNU/Linux上工作。
在OS X、OpenBSD和NetBSD的tcsh上测试,在Debian GNU/Linux的bash上测试。
对话:
在OS X上的tcsh中,下面的sed代码片段可以与printf一起使用,因为sed和echo都不像GNU那样以特殊的方式处理\r:
sed `printf 's/\r$//g'` input > output
tr:
另一个选项是tr:
tr -d '\r' < input > output
sed和tr的区别:
看起来tr从输入文件中保留了一个尾随换行符,而在OS X和NetBSD(但在OpenBSD或GNU/Linux上没有)上的sed在文件的最后插入一个尾随换行符,即使输入在文件的最后缺少任何尾随\r或\n。
测试:
这里有一些测试示例,可以使用printf和hexdump -C来确保它在您的系统上工作;另外,如果你的系统缺少hexdump,也可以使用od -c:
% 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
%
我制作了这个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
使用sed
sed $'s/\r//' infile > outfile
在Git Bash for Windows上使用sed
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,则更多)。只有在确定文件不包含特殊字符或需要展开时才使用它。 警告:没有一个解决方案可以处理输入文件中的\。
推荐文章
- 如何在父进程退出后使子进程死亡?
- Unix列表命令'ls'可以输出数值chmod权限吗?
- 在Unix中,我可以在一个目录中运行'make'而不首先cd'到该目录吗?
- 快速unix命令显示文件中间的特定行?
- 如何生成一个核心转储在Linux上的分段错误?
- 在Python中如何在Linux和Windows中使用“/”(目录分隔符)?
- 使用sh shell比较字符串
- 只列出UNIX中的目录
- 如何限制从grep返回的结果的数量?
- 如何管道列表的文件返回的找到命令到猫查看所有文件
- 以相对于当前目录的路径递归地在Linux CLI中列出文件
- 如何使用xargs复制名称中有空格和引号的文件?
- 在makefile中抑制命令调用的回声?
- Shell脚本for循环语法
- read()和recv(), send()和write()之间有什么区别?