【问题标题】:Google Script: Match RegEx into 2D array谷歌脚本:将正则表达式匹配到二维数组
【发布时间】:2020-04-04 00:12:31
【问题描述】:

我正在尝试将信息从 Gmail 提取到 Google 电子表格中。电子邮件中的信息具有表格结构,其中包含以下列产品列表、已售数量和每个产品的小计。这些重复 N 次。

当使用message.getPlainBody() 访问信息时,我得到以下文本:


Product
Quantity
Price
Chocolate
1
$8.58
Apples
2
$40.40
Bananas
1
$95.99
Candy
1
$4.99
Subtotal:
$149.96

进展

首先我尝试使用正则表达式来识别每一行的所有元素:

  • 产品名称:任意数量的字符,不包括':' (.*)[^:]
  • 售出数量:任意数量 \d*
  • 任何看起来像小计的东西 [$]\d*.\d*

把所有东西都包起来,看起来像这样

    function ExtractDetail(message){
      var mainbody = message.getPlainBody();

     //RegEx
     var itemListRegex = new RegExp(/(.*)[^:][\r\n]+(\d*[\r\n]+[$](\d*\.\d*)[\r\n]+/g);
     var itemList = mainbody.match(itemListRegex);
     Logger.log(itemList);
    }

到目前为止它有效:

itemList: 巧克力 1 $8.58 , 苹果 2 $40.40 , 香蕉 1 $95.99 ,糖果 1 $4.99

但是,我得到以下结果:

  • [巧克力 1 美元 8.58 美元]
  • [苹果 2 美元 40.40 美元]
  • [香蕉 1 美元 95.99 美元]
  • [糖果 1 美元 4.99 美元]

代替:

  • [巧克力] [ 1 ] [$8.58]
  • [苹果] [ 2 ] [$40.40]
  • [香蕉] [ 1 ] [$95.99]
  • [糖果] [ 1 ] [$4.99]

问题

我的问题是,我怎样才能追加一个新行,使每行对应于找到的每个匹配项,并且每列对应于每个属性?

如何将每个匹配的结果转换为数组?是否有可能或者我应该改变我的方法?

更新:

由于我当前尝试的结果是一个大字符串,我正在尝试寻找其他选项。弹出这个:

var array = Array.from(mainbody.matchAll(itemListRegex), m => m[1]);

来源:How do you access the matched groups in a JavaScript regular expression?

我还在努力。我仍然需要找到如何添加更多列,并且由于某种原因它从“Apples”开始(按照示例),留下“Chocolates”。

日志:

Logger.log('array: ' + array);

【问题讨论】:

  • 如果我误解了您的问题,我深表歉意。您能否再次确认您的问题中的脚本(尤其是正则表达式)是否正确?我认为您可能没有正确复制它。
  • @Tanaike 嗨 Tanaike。这是正确的,至少它找到了它被要求的东西。主要问题是将找到的信息放入二维数组中。我稍后会发布更新。
  • 感谢您的回复。您问题中的脚本是正确的。我的理解正确吗?而且,我认为当您提供itemList 的示例值作为文本值时,它将帮助用户思考解决方案。因为在您的情况下,这些值在图像中。
  • 更新了!该脚本部分正确。目标是从 RegEx 中获取结果并将它们作为表格写在表格中。此时我能得到的只是一个长字符串,我正试图以某种方式将其转换为二维数组。
  • 田池所说的是正则表达式无效

标签: regex google-apps-script multidimensional-array google-sheets


【解决方案1】:

如果你想像Array.from(mainbody.matchAll(itemListRegex), m => m[1])一样使用matchAll,这个修改怎么样?

在这种情况下,/(.*[^:])[\r\n]+(\d*)[\r\n]+([$]\d*\.\d*)[\r\n]/g 用作正则表达式。

修改脚本:

const itemListRegex = /(.*[^:])[\r\n]+(\d*)[\r\n]+([$]\d*\.\d*)[\r\n]/g;
var array = Array.from(mainbody.matchAll(itemListRegex), ([,b,c,d]) => [b,Number(c),d]);

结果:

[
  ["Chocolate",1,"$8.58"],
  ["Apples",2,"$40.40"],
  ["Bananas",1,"$95.99"],
  ["Candy",1,"$4.99"]
]

脚本测试:

const mainbody = `
Product
Quantity
Price
Chocolate
1
$8.58
Apples
2
$40.40
Bananas
1
$95.99
Candy
1
$4.99
Subtotal:
$149.96
`;

const itemListRegex = /(.*[^:])[\r\n]+(\d*)[\r\n]+([$]\d*\.\d*)[\r\n]/g;
var array = Array.from(mainbody.matchAll(itemListRegex), ([,b,c,d]) => [b,Number(c),d]);
console.log(array)

注意:

  • 关于how can I append a new row in a way that it each row corresponds to each match found and that each column corresponds to each property?,这意味着将值放入电子表格吗?如果是这样,您能否提供您期望的示例结果?

参考资料:

【讨论】:

  • 伙计,我觉得我真的很接近答案,但每天我们都会学到新东西。非常感谢您的详细解答!
  • @Luis Alberto Delgado de la Flo 感谢您的回复。很高兴您的问题得到解决。
【解决方案2】:

Mapsplit 通过\new 行得到的数组:

const data = `Product
Quantity
Price
Chocolate
1
$8.58
Apples
2
$40.40
Bananas
1
$95.99
Candy
1
$4.99
Subtotal:
$149.96`;

const itemListRegex = /.*[^:][\r\n]+\d*[\r\n]+\$\d*\.\d*(?=[\r\n]+)/g;
const itemList = data.match(itemListRegex);

console.info(itemList.map(e => e.split(/\n/)));//map and split

【讨论】:

  • 非常感谢TheMaster的回答。它也对我有用。
猜你喜欢
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 2013-04-14
  • 2015-12-25
  • 2016-08-21
相关资源
最近更新 更多