在 OSX 上,我需要从我的 CSV 文件中删除行尾 CR ( \r
) 字符(在 ^M
的输出中表示为 cat -v
):
$ cat -v myitems.csv
输出:
strPicture,strEmail^M
image1xl.jpg,me@example.com^M
我用 sed 和 perl 尝试了很多选项,但没有任何效果。
有任何想法吗?
最佳答案
库存实用程序的解决方案 :
注意:除非另有说明(sed -i
不兼容),以下解决方案适用于 OSX (macOS) 和 Linux。
使用sed
如下,替换\r\n
与 \n
:
sed $'s/\r$//' myitems.csv
要更新输入文件,请使用
sed -i '' $'s/\r$//' myitems.csv
-i ''
使用 ''
指定就地更新表示不应对输入文件进行备份;如果您指定扩展名,例如 -i'.bak'
,原始输入文件将以该扩展名保存为备份。注意事项:
* 与 GNU
sed
(Linux) ,要不创建备份文件,您必须使用 只是 -i
, 没有单独的 ''
论据 ,即 不幸的是 GNU Sed 和 BSD Sed 之间的语法不兼容 用于 OSX (macOS) - 见 this answer我的完整故事。*
-i
使用临时名称创建一个新文件,然后替换原始文件;最显着的后果是,如果原始文件是符号链接(symbolic link),则将其替换为常规文件;详细讨论见this answer的下半部分.注意:以上使用 ANSI C-quoted string (
$'...'
) 创建 \r
sed
中的字符命令,因为 BSD sed
(在 OS X 上使用的那个)本身不能识别这样的转义序列(请注意,在 Linux 发行版上使用的 GNU sed
会)。Bash、Ksh 和 Zsh 支持 ANSI C 引用的字符串。
如果您不想依赖此类字符串,请使用:
sed 's/'"$(printf '\r')"'$//'
在这里,
\r
通过 printf
创建并拼接到sed
带有命令替换的命令 ( $(...)
)。使用
perl
: perl -pe 's/\r\n/\n/' myitems.csv | cat -v
要更新输入文件,请使用
perl -i -ple 's/\r\n/\n/' myitems.csv # -i'.bak' creates backup with suffix '.bak' first
与上述
sed
相同的警告关于就地更新适用。使用
awk
: awk '{ sub("\r$", ""); print }' myitems.csv # shorter: awk 'sub("\r$", "")+1'
BSD
awk
不提供就地更新选项,因此您必须在不同的文件中捕获输出;要使用临时文件并在之后替换原始文件,请使用以下成语:awk '{ sub("\r$", ""); print }' myitems.csv > tmpfile && mv tmpfile myitems.csv
GNU
awk
v4.1 或更高版本提供-i inplace
对于就地更新,与上述 sed
的警告相同适用。上述所有变体的边缘情况:如果最后一个字符。在输入文件中恰好是一个单独的
\r
没有后续\n
,它也将被替换为 \n
.为了完整起见:这里是额外的,可能是次优的解决方案 :
它们都不提供就地更新,但您可以使用
> tmpfile && mv tmpfile myitems.csv
上面介绍的成语使用
tr
:一个非常简单的解决方案,只需删除所有 \r
实例;因此,它只能在 \r
时使用实例仅作为 \r\
的一部分出现n个序列;然而,通常情况就是这样:tr -d '\r' < myitems.csv
使用纯
bash
代码 :请注意,这会很慢;喜欢 tr
解决方案,这只能在 \r
时使用实例仅作为 \r\n
的一部分出现序列。while IFS=$'\r' read -r line; do
printf '%s\n' "$line"
done < myitems.csv
$IFS
是内部字段分隔符,并将其设置为 \r
原因 read
阅读 \r
之前的所有内容,如果存在,进入变量 $line
(如果没有 \r
,则按原样读取该行)。 -r
防止read
来自口译\
输入中的实例。边缘情况:如果输入不以
\n
结尾,最后一行将不会打印 - 您可以使用 read -r line || [[ -n $line ]]
来修复它.
关于macos - 从 CSV 中删除\r (CR),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21640902/