我似乎没有找到与此确切问题相匹配的SO问题。
我有一个文本文件,每行有一个文本标记,没有任何逗号,制表符或引号。我想根据文件内容创建一个逗号分隔的字符串。
输入:
one
two
three
输出:
one,two,three
我正在使用此命令:
csv_string=$(tr '\n' ',' < file | sed 's/,$//')
有没有更有效的方法来做到这一点?
执行此操作的通常命令是paste
csv_string=$(paste -sd, file.txt)
与Awk
的一种方法是重置RS
并将记录视为由空行分隔。这将处理带空格的单词,并按预期格式化为CSV格式。
awk '{$1=$1}1' FS='\n' OFS=',' RS= file
{$1=$1}
是一种基于对Field($0
)和/或Record分隔符(FS/OFS
)的修改来重建文件的每一行(RS/ORS
)中的字段的方法。尾随的1
是打印每一行,在{..}
内进行修改。
您可以使用bash参数扩展运算符完全执行此操作,而不是使用tr
和sed
。
csv_string=$(<file) # read file into variable
csv_string=${csv_string//$'\n'/,} # replace \n with ,
csv_string=${csv_string%,} # remove trailing comma
使用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盒子上的四种方法 - Bash only,paste,awk,Perl,以及问题中显示的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
,Awk
和perl
:
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上。
相关文章: