我正在处理一个大型 csv 文件,其中包含所有逗号分隔的条目。整个文档由纯数字组成,除了几列反映格式化为文本的货币之外。例如,一个这样的条目可能看起来相似"$12,345.67"
,而另一个条目也可能相似"$1,234,567.89"
(双引号符号也包含在条目中)。以下是完整数据记录(一行)的示例:
123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2
我想对此数据文件进行一些处理,因此,我想将此类文本字段重新格式化为纯数字(即摆脱双引号和逗号)。我认为正则表达式模式替换sed
应该适合我,但我根本不确定正则表达式是什么样的。任何想法将不胜感激。
答案1
表达应该做什么很简单:
"$
1 对于和之间包含的每个字符串,"
删除所有,
2 删除周围的"$
和"
这是 sed 表达式。如果您在命令行上使用它,则必须适当地引用它。将它放在一个文件中更简单,例如command.sed,然后通过以下方式调用它
sed -f command.sed data.csv
这是实现这两个步骤的程序:
:repeat
s/"\$\([^,"]*\),/"$\1/g
t repeat
s/"\$\([^"]*\)"/\1/g
这文档帮助我解决了问题。
答案2
更新:调整答案仅替换引号之间的空格来处理这个问题。
命令:
echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2' |
awk -F\" '{OFS="\""; for (i = 2; i < NF; i += 2) gsub(/[$,]/,"",$i); gsub(/"/,""); print}'
输出:
123,7,11,343700.14,34928.63,377000.00,15421.92,19,2
第一个gsub
删除双引号内的$
s 和s。,
第二个删除引号本身。
在下面留下原始答案以防有帮助。
如果我理解正确的话,简单的搜索和替换就可以了
echo '"$1,234,567.89"' | sed 's/[$,"]//g'
输出1234567.89
。
其作用是替换与 ( ) 匹配的 ( )s
字符,并且不替换任何内容(最后两个 之间为空。该标志使其全局适用,替换所有实例(否则仅替换行中的第一个实例)。[]
$
,
"
/
g
如何将其应用于整个文件取决于文件的格式。如果文件中没有其他内容包含双引号、美元符号和逗号,则应该很好:
sed 's/[$,"]//g' /path/to/file
答案3
此货币值的显示方式取决于您的 CSV 查看器,为什么您不更改 Excel 中的“视图”而不是更改此字段?
不管怎样,您的 csv 字段中可能有多个字段,因此使用如下处理程序脚本会更安全:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV;
my $csv = Text::CSV->new ( { binary => 1 } );
while ( my $row = $csv->getline(\*STDIN) ) {
foreach my $item (@$row)
{
$item =~ s/,//g if ($item =~ /^\$[0-9,.]+$/);
}
$csv->print (\*STDOUT, $row);
print "\n";
}
用法:./csv.pl < in.csv > ou.csv
输入:
abc,"$1,243,311.99",def
abc2,"$43,311.99",def2
输出:
abc,$1243311.99,def
abc2,$43311.99,def2
答案4
一个稍微复杂的 awk 解决方案,基于使用 awk 解析 CSV
{
$0=$0","; # yes, cheating
while($0) {
gsub(/\$/,"",$0)
match($0,/ *"[^"]*" *,|[^,]*,/);
sf=f=substr($0,RSTART,RLENGTH); # save what matched in sf
gsub(/^ *"?|"? *,$/,"",f); # remove extra stuff
gsub(/,/,"",f);
if($0 ~ /,[^,]+,$/){
printf "%s,",f;
}else{
printf "%s",f;
}
sub(sf,""); # "consume" what matched
}
printf "\n"
}
将上面的内容保存为 csv.awk 并像这样运行:
echo '123,7,11,"$343,700.14","$34,928.63","$377,000.00","$15,421.92",19,2'|awk -f csv.awk
123,7,11,343700.14,34928.63,377000.00,15421.92,19,2