Bash - 正则表达式提取气道账单号码

时间:2018-06-15 19:59:54

标签: regex bash grep

我有一个文本文件,其中包含一些航空公司账号:

Pesanan anda telah dikirim oleh jasa pengiriman NinjaVanID dengan nomor resi NLIDRT0000399000
Paket telah dikirim melalui TIKI. no.resi 885000210000. Cek status pesanan di https://example.com/resi/
Pesanan telah dikirim melalui JNE. no.resi JNRP-0000708000. Cek status H+1 di www.example.co.id or atau menghubungi 021-2927.0000
Pesanan anda telah dikirim oleh jasa pengiriman LEX ID dengan nomor resi LXRP-9295841000

我想提取这些空运提单编号:

NLIDRT0000399000
885000210000
JNRP-0000708000
LXRP-9295841000

以下是规则:

  1. 前缀NLIDRT JNRP- LXRP-始终相同,只有背后的数字不同
  2. 885000210000这个没有任何前缀,只有数字,它们总是会改变。
  3. 文本的其余部分不会改变。只有改变的AWB。
  4. 这是我到目前为止所尝试的但不起作用:

    grep -e 'NLIDRT\K(\d+)' -e 'TIKI, no\.resi \K(\d+)' -e 'JNRP-\K(\d+)' -e 'LXRP-\K(\d+)' awb.txt
    

    我该怎么做?命令无关紧要,可以是awk / grep / sed

2 个答案:

答案 0 :(得分:0)

  • 示例:

    grep -Eo '\<((NLIDRT|JNRP-|LXRP-)[0-9]{10}|[0-9]{12})\>' <<\eof
    Pesanan anda telah dikirim oleh jasa pengiriman NinjaVanID dengan nomor resi NLIDRT0000399000
    Paket telah dikirim melalui TIKI. no.resi 885000210000. Cek status pesanan di https://example.com/resi/
    Pesanan telah dikirim melalui JNE. no.resi JNRP-0000708000. Cek status H+1 di www.example.co.id or atau menghubungi 021-2927.0000
    Pesanan anda telah dikirim oleh jasa pengiriman LEX ID dengan nomor resi LXRP-9295841000
    eof
    
  • 结果:

    NLIDRT0000399000
    885000210000
    JNRP-0000708000
    LXRP-9295841000
    
  • 说明:

    grep -Eo '\<((NLIDRT|JNRP-|LXRP-)[0-9]{10}|[0-9]{12})\>'
    
  • \<表示单词的开头(这样我们就不会在单词内部开始匹配;例如我们不应该匹配XJNRP-

    < / LI>
  • 有两种选择:(带前缀或|带前缀)

  • 带前缀的变体为(NLIDRT|JNRP-|LXRP-)[0-9]{10},即( NLIDRTJNRP-LXRP- )之一10位数。

  • 不带前缀的变体是12位数。

  • \>表示单词结束,因此我们不会匹配较长的数字序列或类似...89XX的内容。

请注意grep -E启用扩展正则表达式。

请注意,10位和12位数的规则是我的印象,可能是错误的。如果您想要一个或多个数字(而不是10和12),请说[0-9]+。如果您想要10个或更多人说[0-9]{10,}

答案 1 :(得分:0)

您使用的是与PCRE兼容的模式,其中\d matches digits\Kmatch reset operator,省略了到目前为止匹配的全文。这不是你需要的,因为前缀是预期匹配的一部分。

我建议使用

grep -oE '(TIKI\. *no\.resi *|NLIDRT|JNRP-|LXRP-)?[0-9]{10,}'

-o选项使grep返回匹配的子字符串,而不是匹配发生的整行。

POSIX ERE模式(由于-E选项)匹配

  • (TIKI\. *no\.resi *|NLIDRT|JNRP-|LXRP-)? - 一个可选的(1或0次)子字符串:
    • TIKI\. *no\.resi * - TIKI.,然后是0 +空格,no.resi和0+空格(用[[:space:]]替换空格以匹配任何空格)
    • | - 或
    • NLIDRT - NLIDRT substring
    • | - 或
    • JNRP- - JNRP- substring
    • | - 或
    • LXRP- - LXRP- substring
  • [0-9]{10,} - 10位或更多位数。

注意:如果要将这些AWB作为整个单词进行匹配(如果没有字母,数字和_字符“粘在一起”),您可以使用字边界

grep -oE '\b(TIKI\. *no\.resi *|NLIDRT|JNRP-|LXRP-)?[0-9]{10,}\b'

grep -oE '\<(TIKI\. *no\.resi *|NLIDRT|JNRP-|LXRP-)?[0-9]{10,}\>'

其中\b是单词/非单词char之间的字符串中的位置,或者字符串的开头和单词char之间,或单词char和字符串结尾之间的位置,\<匹配非单词char /字符串开头和单词char(前导单词边界)之间的位置,\>是结束单词边界(单词和非单词char /字符串结尾之间的位置。

请参阅grep demo online

s='Pesanan anda telah dikirim oleh jasa pengiriman NinjaVanID dengan nomor resi NLIDRT0000399000
Paket telah dikirim melalui TIKI. no.resi 885000210000. Cek status pesanan di https://www.jne.co.id/resi/
Pesanan telah dikirim melalui JNE. no.resi JNRP-0000708000. Cek status H+1 di www.jne.co.id or atau menghubungi 021-2927.8888
Pesanan anda telah dikirim oleh jasa pengiriman LEX ID dengan nomor resi LXRP-9295841000'

echo "$s" | grep -oE '(TIKI\. *no\.resi *|NLIDRT|JNRP-|LXRP-)?[0-9]{10,}'

结果:

NLIDRT0000399000
TIKI. no.resi 885000210000
JNRP-0000708000
LXRP-9295841000