如何用Ruby从发票文本中正确提取INVOICE #对应的发票号
发票号提取功能修正方案
问题根因
原有提取逻辑和当前发票文本的排版结构不匹配,直接导致取数错误:
- 源文本中
INVOICE #是表头行的第一个字段,同一行后续依次排列DATE、TOTAL DUE、DUE DATE等其他表头名称 - 原逻辑匹配到
INVOICE #关键词后,直接切分取后方内容的第一个非空片段,拿到的自然是同属表头的DATE,和预期结果不符 - 实际发票号
31104不在表头所在行,位于表头行下一行最左侧位置,属于跨行列固定排版结构,原有逻辑完全未覆盖该场景。
适配当前场景的稳定提取代码
def extract_invoice_no(msgBody) # 忽略大小写匹配各类INVOICE #写法,兼容空格、符号差异 invoice_header_regex = /INVOICE\s*#/i header_match = msgBody.match(invoice_header_regex) return '' unless header_match # 定位到表头之后的内容,跳过空行找到下一个有效行 content_after_header = msgBody[header_match.end..] next_valid_line = content_after_header.lines.map(&:strip).reject(&:empty?).first return '' unless next_valid_line # 取该行最左侧的第一个连续片段,即为对应位置的发票号 next_valid_line.split(/\s+/).first end
运行效果
对给定的发票源文本调用该方法,将稳定返回31104,不会错取到表头字段DATE。
兼容多场景的增强版提取逻辑
如果需要适配更多不同排版的发票(比如部分发票为关键词后同一行直接跟值,部分为跨行列排版),可使用兼容写法:
def extract_invoice_no(msgBody) # 统一匹配所有常见的发票号标识,忽略大小写、写法差异 pattern = /(invoice\s*#|invoice\s*number|invoice\s*no|invoicenumber)/i match_res = msgBody.match(pattern) return '' unless match_res content_after = msgBody[match_res.end..] content_blocks = content_after.split(/\s+/).reject(&:empty?) # 过滤掉明显的表头字段,第一个有效业务值即为发票号 invalid_headers = %w[date total due terms enclosed balance] content_blocks.reject{ |block| invalid_headers.include?(block.downcase) }.first end
该写法同时兼容原代码适配的「关键词后紧跟值」的老式文本结构,也能正确解析当前多列表头排版的发票内容。
内容的提问来源于stack exchange,提问作者Naresh Kumar P
相关产品推荐
相关产品推荐

