繁体   English   中英

将文本文件转换为逗号分隔的字符串

[英]Convert text file into a comma delimited string

我似乎没有找到与这个确切问题匹配的 SO 问题。

我有一个文本文件,每行有一个文本标记,没有任何逗号、制表符或引号。 我想根据文件内容创建一个逗号分隔的字符串。

输入:

one
two
three

Output:

one,two,three

我正在使用这个命令:

csv_string=$(tr '\n' ',' < file | sed 's/,$//')

有没有更有效的方法来做到这一点?

执行此操作的常用命令是粘贴

csv_string=$(paste -sd, file.txt)

您可以使用bash参数扩展运算符完全执行此操作,而不是使用trsed

csv_string=$(<file)               # read file into variable
csv_string=${csv_string//$'\n'/,} # replace \n with ,
csv_string=${csv_string%,}        # remove trailing comma

使用Awk一种方法是重置RS并将记录视为由空行分隔。 这将处理带空格的单词,并按预期格式化为CSV格式。

awk '{$1=$1}1' FS='\n' OFS=',' RS= file

{$1=$1}是一种基于对Field( FS/OFS )和/或Record分隔符( RS/ORS )的修改来重建文件每行( $0 )中字段的方法。 尾随1是打印每一行,并在{..}内完成修改。

使用Perl one-liner:

$ cat csv_2_text
one
two
three
$ perl -ne '{ chomp; push(@lines,$_) } END { $x=join(",",@lines);  print "$x" }' csv_2_text
one,two,three

$ perl -ne ' { chomp; $_="$_," if not eof ;printf("%s",$_) } ' csv_2_text
one,two,three
$

来自@codeforester

$ perl -ne 'BEGIN { my $delim = "" } { chomp; printf("%s%s", $delim, $_); $delim="," } END { printf("\n") }' csv_2_text
one,two,three
$

在Linux机器上测试了四种方法 - 仅限BashpasteawkPerl以及tr | sed 问题中显示的tr | sed方法:

#!/bin/bash

# generate test data
seq 1 10000 > test.file

times=${1:-50}

printf '%s\n' "Testing paste solution"
time {
    for ((i=0; i < times; i++)); do
      csv_string=$(paste -sd, test.file)
    done
}

printf -- '----\n%s\n' "Testing pure Bash solution"
time {
    for ((i=0; i < times; i++)); do
      csv_string=$(<test.file)          # read file into variable
      csv_string=${csv_string//$'\n'/,} # replace \n with ,
      csv_string=${csv_strings%,}       # remove trailing comma
    done
}

printf -- '----\n%s\n' "Testing Awk solution"
time {
    for ((i=0; i < times; i++)); do
      csv_string=$(awk '{$1=$1}1' FS='\n' OFS=',' RS= test.file)
    done
}

printf -- '----\n%s\n' "Testing Perl solution"
time {
    for ((i=0; i < times; i++)); do
      csv_string=$(perl -ne '{ chomp; $_="$_," if not eof; printf("%s",$_) }' test.file)
    done
}

printf -- '----\n%s\n' "Testing tr | sed solution"
time {
    for ((i=0; i < times; i++)); do
      csv_string=$(tr '\n' ',' < test.file | sed 's/,$//')
    done
}

令人惊讶的是,Bash唯一的解决方案确实很糟糕。 paste在顶部,然后是tr | sed tr | sedAwkperl

Testing paste solution

real    0m0.109s
user    0m0.052s
sys 0m0.075s
----
Testing pure Bash solution

real    1m57.777s
user    1m57.113s
sys 0m0.341s
----
Testing Awk solution

real    0m0.221s
user    0m0.152s
sys 0m0.077s
----
Testing Perl solution

real    0m0.424s
user    0m0.388s
sys 0m0.080s
----
Testing tr | sed solution

real    0m0.162s
user    0m0.092s
sys 0m0.141s

出于某些原因, csv_string=${csv_string//$'\\n'/,}挂在运行Bash 4.4.23的macOS Mojave上。


相关文章:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM