【发布时间】:2016-06-06 15:06:39
【问题描述】:
我有一个大的 csv 文件,每行大约有 100 个双引号“文本字段”。许多行在双引号字段中嵌入了 \r\n。 \r\n 对也用于行终止。
如何从双引号字段中删除 \r\n 对而不影响 \r\n 行终止。
我尝试创建单独的 sed 脚本来识别特定的嵌入序列。那种工作,但脚本的数量变得难以管理。我也尝试过使用 'tr -d '\r' 命令,但没有成功。
【问题讨论】:
标签: csv
我有一个大的 csv 文件,每行大约有 100 个双引号“文本字段”。许多行在双引号字段中嵌入了 \r\n。 \r\n 对也用于行终止。
如何从双引号字段中删除 \r\n 对而不影响 \r\n 行终止。
我尝试创建单独的 sed 脚本来识别特定的嵌入序列。那种工作,但脚本的数量变得难以管理。我也尝试过使用 'tr -d '\r' 命令,但没有成功。
【问题讨论】:
标签: csv
为此,您可以使用perl。
perl -0pe 's/"(.*?)([[:space:]]+)(.*?)"/"\1 \3"/g' input.csv > output.csv
perl -pe 's/../../g' file 类似于sed -e 's/../../g' file,但使用Perl compatible regular expressions (PCRE)。请参阅this 或this 了解更多详情。
使用 zero perl -0 选项,我们将 null 字符 视为输入记录分隔符(请参阅 xargs -0 ... 或 find . -print0 ...)。
sed 的所有版本都支持 Basic Regular Expressions (BRE),而某些版本,如 GNU sed(使用 sed -E),支持 BRE 的超集 Extended Regular Expressions (ERE)。在 BRE 和 ERE 中,量词 * 和 + 总是贪婪的,它们匹配尽可能多的字符。然而,在某些情况下,我们需要匹配尽可能少的字符。使用 PCRE,我们可以使用 *? 和 +? 来做量词 * 和 + lazy 或 minimal 或 relucant分别。
为了删除双引号内的\r\n,保留任何其他换行符,我们使用惰性匹配:"(.*?)([[:space:]]+)(.*?)"。我们还使用backreferences "\1 \3" 省略第二个匹配的括号,其中包含任何空格序列(字符\t、\r、\n、\v或\f) ,特别是\r\n的序列。
这种方法适用于 CSV 文件,其中“行有 a \r\n 嵌入在双引号字段中”就像您的情况一样。如果input.csv 包含的单元格包含三个或更多以\r\n 分隔的段落,我们必须修改正则表达式。
【讨论】: