从 Unix 文件中删除所有回车 \r
的最简单方法是什么?
tr -d
命令是最简单的方法,但我想知道如何仅删除 最后一个回车符?
我将假设您的意思是回车(CR, "\r"
, 0x0d
)在行的ends,而不是盲目地在文件中(您可以据我所知,将它们放在字符串中间)。仅在第一行末尾使用带有 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
请参阅tr(1)
tr
不支持 \r
转义,请尝试 '\015'
或文字 '^M'
(在许多终端上的许多 shell 中,ctrl-V ctrl-M 将产生文字 ctrl-M 字符)。
outfile = infile
时如何改变它呢?
someProg <in >out && mv out in
。
在我看来,Linux 上最简单的方法是,
sed -i.bak 's/\r$//g' <filename>
-i 将在原地编辑文件,而 .bak 将通过制作文件副本并添加扩展名 来创建原始文件的备份。 bak 在最后。 (您可以在 -i
之后指定您想要的任何内容,或仅指定 -i
以不创建备份。)
替换运算符 's/\r//'
周围的强引号是必不可少的。没有它们,shell 会将 \r
解释为 escape+r 并将其简化为纯 r
,并删除所有小写 r
。这就是 Rob 在 2009 年上面给出的答案不起作用的原因。
添加 /g
修饰符可确保删除多个 \r
,而不仅仅是第一个。
-i
标志,因为它会修改原始文件,如果您希望保持不变,可能会很危险
老套:
tr -d '\r' < filewithcarriagereturns > filewithoutcarriagereturns
许多系统上都有一个名为 dos2unix 的实用程序,并且可以在大多数系统上轻松安装。
sed -i s/\r// <filename>
或类似的东西;请参阅 man sed
或网络上有关使用 sed
的大量信息。
需要指出的一点是上面“回车”的确切含义;如果您真正的意思是单个控制字符“回车”,那么上面的模式是正确的。如果您的意思是,更一般地说,CRLF(回车和换行,这是在 Windows 下实现换行的方式),那么您可能想要替换 \r\n
。 Linux/Unix 中的裸换行符(换行符)是 \n
。
s/\r//
似乎没有删除 OS X 上的回车符,它似乎删除了文字 r
字符。我不确定为什么会这样。也许它与引用字符串的方式有关?作为一种解决方法,使用 CTRL-V + CTRL-M
代替 \r
似乎可行。
如果您是 Vi 用户,您可以使用以下命令打开文件并删除回车:
:%s/\r//g
或与
:1,$ s/^M//
请注意,您应该通过按 ctrl-v 然后按 ctrl-m 来输入 ^M。
^M
-s。解决这个问题需要大量的击键,这不是 vim 的用途;)。我只选择 sed -i
,然后使用 `-e 's/\r$//g' 将删除限制为 EOL 时的 CR。
其他人推荐 dos2unix
,我也强烈推荐它。我只是提供更多细节。
如果已安装,请跳至下一步。如果尚未安装,我建议通过 yum
安装它,例如:
yum install dos2unix
然后你可以像这样使用它:
dos2unix fileIWantToRemoveWindowsReturnsFrom.txt
又是一个解决方案……因为总会有一个解决方案:
perl -i -pe 's/\r//' filename
这很好,因为它已经到位并且适用于我使用过的各种 unix/linux。
-i.bak
。
在任何 UNIX® 系统上删除 \r:
这个问题中的大多数现有解决方案都是特定于 GNU 的,并且不适用于 OS X 或 BSD;下面的解决方案应该可以在更多的 UNIX 系统上运行,并且可以在从 tcsh
到 sh
的任何 shell 中运行,但即使在 GNU/Linux 上也仍然可以运行。
在 tcsh
中的 OS X、OpenBSD 和 NetBSD 以及 bash
中的 Debian GNU/Linux 上进行了测试。
使用 sed:
在 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
%
如果您使用的操作系统(如 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
a * b
的文件...
事情是这样的,
%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 Code: How to show line endings
只需转到屏幕的右下角,Visual Studio 代码就会向您显示文件编码和文件后跟的行尾约定,只需单击一下即可切换。
只需在 linux 环境中使用可视代码作为 notepad++ 的替代品,您就可以开始使用了。
Notepad++
的命令 Edit / EOL Conversion / Unix (LF)
。
使用 sed
sed $'s/\r//' infile > outfile
在 Windows 版 Git Bash 上使用 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
,则为 *
、?
、[...]
等)。仅当您确定文件不包含特殊字符或您想要扩展时才使用它。
警告:没有任何解决方案可以处理输入文件中的 \
。
cat input.csv | sed 's/\r/\n/g' > output.csv
为我工作
我用过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
不定期副业成功案例分享
\r
仅适用于 GNU sed,否则您可以这样做:sed `echo "s/\r//"`
sed
和echo
在 MacO 上都不能识别\r
。在这种情况下,只有printf "\r"
似乎有效。sed "s/$(printf '\r')\$//"
$
,如下所示:sed $'s@\r@@g' |od -c
(但如果您要替换为\n
,则需要对其进行转义)CTRL-V + CTRL-M
代替\r
看起来可能会起作用。