删除 CSV 中数字的千位分隔符(批处理命令,使用 JREPL)

remove thousand separator of number in CSV (batch command, using JREPL)

我有以下 csv,我必须将千位逗号分隔符替换为空。在下面的示例中,当我有金额 "1,000.00" 时,我应该使用 1000.00 (没有逗号,没有引号)。

我使用 JREPL 从我的 csv

中删除 header
jrepl "(?:.*\n){1,1}([\s\S]*)" "" /m /f "csv/Transactions.csv" /o "csv/Transactionsfeed.csv")

我想知道我是否可以一步完成删除 header + 处理千位逗号的过程。 我也愿意在第二步中使用另一个命令来执行此操作...

Tnx ID,Trace ID - Gateway,Profile,Customer PIN,Customer,Ext. ID,Identifier,Amount,Chrg,Curr,Processor,Type,Status,Created By,Date Created,RejectReason
1102845,3962708,SL,John,Mohammad Alo,NA,455015*****9998,900.00,900.00,$,Un,Credit Card,Rejected,Internet,2016-05-16 06:54:10,"-330: Fail by bank, try again later(refer to acquirer)"
1102844,3962707,SL,John,Mohammad Alo,NA,455015*****9998,"1,000.00","1,000.00",$,Un,Credit Card,Rejected,Internet,2016-05-16 06:52:26,"-330: Fail by bank, try again later(refer to acquirer)"

是的,有一个非常有效且相当紧凑且 straight-forward 的解决方案:

jrepl "\q(\d{1,3}(?:,\d{3})*(?:\.\d*)*)\q" ".replace(/,/g,'')" /x /j /jendln "if (ln==1) $txt=false" /f "csv/Transactions.csv" /o "csv/Transactionsfeed.csv"

/JENDLN JScript 表达式通过将 $txt 设置为 false(如果它是第一行)来剥离 header 行。

搜索字符串匹配任何包含逗号作为千位分隔符的引号,$1 是不带引号的数字。

替换字符串是一个 JScript 表达式,它将匹配的 $1 数字中的所有逗号替换为空。

编辑

请注意,以上内容可能适用于您可能拥有的任何 CSV。但是,如果您有一个包含带引号的数字字符串文字的带引号字段,它将失败。像下面这样的东西会用上面的代码产生一个损坏的 CSV:

...,"some text ""123,456.78"" more text",...

这个问题可以用更多的正则表达式代码来解决。如果开始引号前面有逗号或行首,并且结束引号后面应该有逗号或行尾,您只想修改引用的数字。

look-ahead 断言可用于尾随 comma/EOL。但是JREPL不支持look-behind。所以前导 comma/BOL 必须被捕获并保留在替换

jrepl "(^|,)\q(\d{1,3}(?:,\d{3})*(?:\.\d*)*)\q(?=$|,)" "+.replace(/,/g,'')" /x /j /jendln "if (ln==1) $txt=false" /f "csv/Transactions.csv" /o "csv/Transactionsfeed.csv"

编辑以响应评论中不断变化的要求

以下将简单地从带引号的 CSV 字段中删除所有引号和逗号。我不喜欢这个概念,我怀疑有更好的方法来处理这个导入 mysql,但这正是 OP 所要求的。

jrepl "(^|,)(\q(?:[^\q]|\q\q)*\q)(?=$|,)" "+.replace(/,|\x22/g,'')" /x /j /jendln "if (ln==1) $txt=false" /f "csv/Transactions.csv" /o "csv/Transactionsfeed.csv"

我可以向您推荐一个不同的、更简单的解决方案吗?下面的 5 行批处理文件做你想做的;使用 .bat 扩展名保存它:

@set @a=0  /*
@cscript //nologo //E:JScript "%~F0" < "csv/Transactions.csv" > "csv/Transactionsfeed.csv"
@goto :EOF */

WScript.Stdin.ReadLine();
WScript.Stdout.Write(WScript.Stdin.ReadAll().replace(/(\"(\d{1,3}),(\d{3}\.\d{2})\")/g,""));

JREPL.BAT 是一个庞大而复杂的程序,能够执行高级替换任务;但是,您的要求很简单。此代码也是一个 Batch-JScript 混合脚本,它以与 JREPL.BAT 相同的方式使用 replace 方法,但它是根据您的特定要求量身定制的。

  • 第一个 ReadLine() 读取输入文件的 header 行,因此后 ReadAll() 读取并处理其余行。
  • 正则表达式 (\"(\d{1,3}),(\d{3}\.\d{2})\") 定义了 3 个用括号括起来的子匹配:第一个是用引号括起来的整数,例如 "1,000.00";第二个子匹配是逗号前的数字,第三个子匹配是逗号后的数字,包括小数点。
  • .replace方法改变了之前的正则表达式,即用引号括起来的整数仅由第二个和第三个子匹配。