【发布时间】:2010-08-18 05:57:02
【问题描述】:
我想将制表符分隔的文件转换为 CSV 文件。谁能帮帮我?
【问题讨论】:
我想将制表符分隔的文件转换为 CSV 文件。谁能帮帮我?
【问题讨论】:
OSX 的答案是不同的。
MacOS 无法理解 sed 表达式中的 \t。
您必须使用 ctrl+v 然后 tab 将制表符文字插入 sed 搜索模式(请参阅How can I insert a tab character with sed on OS X?)
sed 's/ /,/g' input_file > output_file
【讨论】:
\t 的 GNU sed。 This question是关于如何安装的。
您可以将 sed 用作:
sed 's/\t/,/g' input_file > output_file
这将保持输入文件不变,并将创建一个带有更改的新文件output_file。
如果您想更改输入文件本身而不创建新文件,您可以使用-i sed 选项来进行就地更改:
sed -i 's/\t/,/g' input_file
【讨论】:
g 在's/\t/,g' 中是什么意思?
g 是启用全局替换.... ref: tutorialspoint.com/unix/unix-regular-expressions.htm "非常重要的是要注意 sed 只替换一行中的第一个出现。如果字符串 root在一行中出现不止一次,只会替换第一个匹配项。要让 sed 执行全局替换,请在命令末尾添加字母 g,如下所示“
sed -i '' 's/foo/goo/g' somefile-name -i 后面的空格用单引号括起来。
请记住,逗号分隔值文件有多种形式。由于您没有指定一个,我假设RFC-4180 格式,UTF-8 编码,TSV 相同,但使用制表符而不是逗号。
天真的方法是简单地用逗号替换每个选项卡:
tr '\t' ,
如果任何值已经包含逗号,或者如果任何值包含带引号的选项卡,则此选项会下降。您需要对文件进行最低限度的解析,以保持引用。与其手动滚动这样的解析器,不如使用已经编写好的解析器更简单、更清晰、更灵活,例如用于 Perl 的 Text::CSV:
#!/usr/bin/perl -w
use Text::CSV;
my $tsv = Text::CSV->new({ sep_char => "\t", auto_diag => 2 });
my $csv = Text::CSV->new();
while (my $row = $tsv->getline(*ARGV)) {
$csv->print(STDOUT, $row) or die $csv->error_diag();
print $/;
}
$csv->error_diag() unless $tsv->eof;
【讨论】:
这也可以用 Perl 来实现:
要将结果通过管道传输到新的输出文件,您可以使用以下命令:perl -wnlp -e 's/\t/,/g;' input_file.txt > output_file.csv
如果您想就地编辑文件,可以调用 -i 选项:perl -wnlpi -e 's/\t/,/g;' input_file.txt
如果您偶然发现您正在处理的实际上不是制表符,而是多个空格,您可以使用以下命令将每个出现的两个或多个空格替换为逗号:perl -wnlpi -e 's/\s+/,/g;' input_file
请记住,\s 代表任何空白字符,包括空格、制表符或换行符,不能在替换字符串中使用。
【讨论】:
在 MacOS 中测试后,这适用于将 csv 文件转换为 tsv 文件(假设列值中不存在制表符或逗号):
cat file_input.tsv | tr '\t' ',' > file_output.csv
我试过了:
sed 's/ /,/g' input_file > output_file
和
sed 's/\t/,/g' input_file > output_file
但是,它们都不起作用。
【讨论】:
cat?有什么原因你不能tr <file_input.tsv吗?我不明白你为什么发布这个,因为你自己承认它只有在值中没有制表符或逗号时才有效,并且有很多具有相同约束的类似答案。
如果 input_file 不包含逗号或带引号的制表符,最简单的方法是使用带有替换正则表达式的 sed 命令,用逗号替换 input_file 中的制表符:
sed 's/\t/,/g' input_file > output_file
当然,input_files 包含引用的选项卡会混淆正则表达式,还有 input_files 的值包含逗号,这些值应该在 output_files 中引用。上面的正则表达式解决方案不足以解决这些情况。
在处理输入文件之前,可以考虑几个 bash 命令来“清理”输入文件...
但是,本着不重新发明轮子的精神。我会使用一个简单的 python3 脚本并将其存储在一个文件中,我们称之为:tsv_to_csv_converter.py:
import csv
import sys
tsv_file = sys.argv[1]
csv_file = sys.argv[2]
in_tsv = csv.reader(open(tsv_file, "r"), delimiter = '\t')
out_csv = csv.writer(open(csv_file, 'w'))
out_csv.writerows(in_tsv)
当然,这段代码可以通过异常捕获、输入值检查、漂亮的 CLI 界面、文档得到显着改进。
脚本可以如下使用:
python3 tsv_to_csv_converter.py input_file output_file
【讨论】:
这是通常的简单问题所有语言的事情吗?好的,这是我的 haskell 解决方案:
main = interact (unlines . replTab . lines) where
replTab l = l >>= (\line ->
"\"" ++ line "\"" >>= \char ->
case char of
'\t' -> "\",\""
'"' -> "\"\""
_ -> [char]
)
未经测试,但应该可以工作。
PS:所有其他解决方案都不知道转义逗号。
【讨论】:
sed -e 's/TAB_CHAR/,/g' data.tsv > data.csv
棘手的部分是如何在命令行中输入 TAB 字符,以做到这一点: 只需按“CTRL+V”,然后按 TAB
我经常将它与带有 -e 参数的 mysql 查询一起使用,如这篇博文 http://blog.modsaid.com/2013/12/exporting-data-from-remote-mysql.html 中所述
【讨论】:
尝试用逗号替换所有选项卡。
如果您没有任何带引号的字段,则可能使用像 s/\t/,/g 这样的正则表达式。
或者,您知道,Excel 可以为您做到这一点。或者 R。或者任何可以接受 TSV 文件的东西。
【讨论】:
在 unix 中:
sed -i -e 's/\t/,/g' filename
【讨论】: