Chinaunix

标题: 文本处理求助 [打印本页]

作者: bikkuri    时间: 2014-08-23 07:38
标题: 文本处理求助
本帖最后由 bikkuri 于 2014-08-23 08:08 编辑

大家好!
我有几个问题向大家请教。
我有一些文本,想从中间提取一些信息。
以下是其中的一个文本。
N9Received: from cloudband-be.local (localhost [127.0.0.1])N:   by cloudband-be.local (Postfix) with ESMTP id 545615405FBN;     for <test@test.com>; Fri, 22 Aug 2014 00:54:12 +0000 (UTC)N+Date: Fri, 22 Aug 2014 00:54:12 +0000 (UTC)N
From: foo@cloud-band.comN
To: test@test.comNHMessage-ID: <346866564.3.1408668852344.JavaMail.ncos@cloudband-be.local>N/Subject: Your CloudBand password has been resetN
MIME-Version: 1.0N'Content-Type: text/plain; charset=UTF-8N
Content-Transfer-Encoding: 7bitN
Dear test test, N
Your password has been reset. N
Username:   test N
E-mail: test@test.com N
Password: EY3vNTKe N
NuTo protect the security of your account our customer service and support personnel will never ask for your password. N
Sincerely, N
CloudBand Customer ServiceX
我希望从这些文本中获取每个用户名、邮件、密码和日期,并以以下方式逐行输出:
  1. Username: test|E-mail: test@test.com|Password: EY3vNTKe|Date: Fri, 22 Aug 2014 00:54:12 +0000 (UTC)
复制代码
那么应该如何处理这些文本呢?
谢谢!
作者: 完美世界吧    时间: 2014-08-23 09:38
前排,哇咔咔
作者: reb00t    时间: 2014-08-23 10:40
  1. <?php

  2. $f = fopen('1.txt','r');
  3. $a = array();
  4. while( !feof($f)){
  5.    $line = fgets($f);
  6.    $pa = '/(Date:[^N]+)|(^Username:[^N]+)|(^E-mail:[^N]+)|(^Password:.* )/';
  7.     preg_match($pa,$line,$tmp);
  8.      if(!empty($tmp)){
  9.       $a[] = $tmp[0];
  10.       }
  11. }
  12. echo  $a[1]."|".$a[2]."|".$a[3]."|".$a[0]."\n";

  13. ?>

  14. Username:   test |E-mail: test@test.com |Password: EY3vNTKe |Date: Fri, 22 Aug 2014 00:54:12 +0000 (UTC)
复制代码

作者: prcardin    时间: 2014-08-23 11:08
膜拜充气大婶的拍黄片
回复 3# reb00t


   
作者: prcardin    时间: 2014-08-23 11:10
膜拜充气大婶的拍黄片
回复 3# reb00t


   
作者: bikkuri    时间: 2014-08-23 12:39
本帖最后由 bikkuri 于 2014-08-23 13:08 编辑

非常感谢您的答复。
我没想到您是用php来做的,因为好像用awk,sed来做文本处理的比较多。
如果用php的话,我还想向您请教一下这个程序的输入的问题。
因为要处理的文件不是一个名为1.txt的文件,而是/var/spool/postfix/deferred/*/*。
另外由于这些文件中含有二进制的非ASCII字符,所以我是用strings命令做预处理将它们变成纯ASCII文本的。
所以在php程序中可以先执行一条system ("strings /var/spool/postfix/deferred/*/* > 1.txt"); 对吧?
但是这样的话,1.txt中会有很多个用户和密码,那php程序要如何修改以处理所有的数据呢?

reb00t 发表于 2014-08-23 10:40

作者: MeRcy_PM    时间: 2014-08-23 13:00
  1. grep -Po 'Username:.*(?=N)|E-mail:.*(?=N)|Password:.*(?=N)|Date:.*(?=N)' urfile | sed ':a N;s/\n/|/g;ta' | awk -F'|' '{print $2"|"$3"|"$4"|"$1}'
复制代码
比较笨,grep出来的顺序和最后输出的顺序不一致,而且有换行不会处理。。。。。。

hrg@linux-xb9s:~/work/shell> cat aaa
N9Received: from cloudband-be.local (localhost [127.0.0.1])N:   by cloudband-be.local (Postfix) with ESMTP id 545615405FBN;     for <test@test.com>; Fri, 22 Aug 2014 00:54:12 +0000 (UTC)N+Date: Fri, 22 Aug 2014 00:54:12 +0000 (UTC)N
From: foo@cloud-band.comN
To: test@test.comNHMessage-ID: <346866564.3.1408668852344.JavaMail.ncos@cloudband-be.local>N/Subject: Your CloudBand password has been resetN
MIME-Version: 1.0N'Content-Type: text/plain; charset=UTF-8N
Content-Transfer-Encoding: 7bitN
Dear test test, N
Your password has been reset. N
Username:   test N
E-mail: test@test.com N
Password: EY3vNTKe N
NuTo protect the security of your account our customer service and support personnel will never ask for your password. N
Sincerely, N
CloudBand Customer ServiceX
hrg@linux-xb9s:~/work/shell> grep -Po 'Username:.*(?=N)|E-mail:.*(?=N)|Password:.*(?=N)|Date:.*(?=N)' aaa | sed ':a N;s/\n/|/g;ta' | awk -F'|' '{print $2"|"$3"|"$4"|"$1}'
Username:   test |E-mail: test@test.com |Password: EY3vNTKe |Date: Fri, 22 Aug 2014 00:54:12 +0000 (UTC)
hrg@linux-xb9s:~/work/shell>
作者: bikkuri    时间: 2014-08-23 13:28
本帖最后由 bikkuri 于 2014-08-23 17:10 编辑

谢谢您的答复,但是好像在处理文本的时候,一部分可以得到正确的输出,另一部分则得不到正确的输出。
以下是一个没有得到正确输出的文本的例子:
N)Received: by cloudband-be.local (Postfix)N6   id E9C79540610; Fri, 22 Aug 2014 08:21:04 +0000 (UTC)N+Date: Fri, 22 Aug 2014 08:21:
04 +0000 (UTC)
N=From: MAILER-DAEMON@cloudband-be.local (Mail Delivery System)N,Subject: Undelivered Mail Returned to SenderN
To: foo@cloud-band.comN
Auto-Submitted: auto-repliedN
MIME-Version: 1.0N<Content-Type: multipart/report; report-type=delivery-status;N5       boundary="571345405FA.1408695664/cloudband-b
e.local"N;Message-Id: <20140822082104.E9C79540610@cloudband-be.local>N
N$This is a MIME-encapsulated message.N
N+--571345405FA.1408695664/cloudband-be.localN!Content-Description: NotificationN*Content-Type: text/plain; charset=us-asciiN
N3This is the mail system at host cloudband-be.local.N
N;I'm sorry to have to inform you that your message could notN<be delivered to one or more recipients. It's attached below.N
N7For further assistance, please send mail to postmaster.N
N9If you do so, please include this problem report. You canN8delete your own text from the attached returned message.N
N"                   The mail systemN
N#<kiyoshi.amemiya@ibm.com>: hostNB    usnavsmail1.ndc.ibm.com[135.3.39.9] said: 550 5.7.1NK    <kiyoshi.amemiya@ibm.com>...
Fix reverse DNS for 135.254.61.241 (inN
     reply to RCPT TO command)N
N+--571345405FA.1408695664/cloudband-be.localN$Content-Description: Delivery reportN%Content-Type: message/delivery-statusN
N&Reporting-MTA: dns; cloudband-be.localN
X-Postfix-Queue-ID: 571345405FAN,X-Postfix-Sender: rfc822; foo@cloud-band.comN3Arrival-Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)N
N4Final-Recipient: rfc822; kiyoshi.amemiya@ibm.comN6Original-Recipient: rfc822;kiyoshi.amemiya@ibm.comN
Action: failedN
Status: 5.7.1N3Remote-MTA: dns; usnavsmail1.ndc.ibm.comNMDiagnostic-Code: smtp; 550 5.7.1 <kiyoshi.amemiya@ibm.com>..
. Fix reverseN
     DNS for 135.254.61.241N
N+--571345405FA.1408695664/cloudband-be.localN(Content-Description: Undelivered MessageN
Content-Type: message/rfc822N
N!Return-Path: <foo@cloud-band.com>N9Received: from cloudband-be.local (localhost [127.0.0.1])N:        by cloudband-be.local (Postf
ix) with ESMTP id 571345405FANI for <kiyoshi.amemiya@ibm.com>; Fri, 22 Aug 2014 08:21:01 +0000 (UTC)N+Date: Fri, 22 Aug 2014 08:
21:01 +0000 (UTC)
N
From: foo@cloud-band.comN
To: kiyoshi.amemiya@ibm.comNIMessage-ID: <1575957485.9.1408695661356.JavaMail.ncos@cloudband-be.local>N/Subject: Your CloudBand
password has been resetN
MIME-Version: 1.0N'Content-Type: text/plain; charset=UTF-8N
Content-Transfer-Encoding: 7bitN
Dear amemiya kiyoshi, N
Your password has been reset. N
Username:   kamemiya N$E-mail: kiyoshi.amemiya@ibm.com N
Password: fpMMduNF N
NuTo protect the security of your account our customer service and support personnel will never ask for your password. N
Sincerely, N
CloudBand Customer ServiceN
N---571345405FA.1408695664/cloudband-be.local--X
处理的结果是:
[root@cloudband-be E]# strings *|grep -Po 'Username:.*(?=N)|E-mail:.*(?=N)|Password:.*(?=N)|Date:.*(?=N)' | sed ':a N;s/\n/|/g;ta' |
awk -F'|' '{print $2"|"$3"|"$4"|"$1}'
Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)|Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)|Username:   kamemiya N$E-mail: kiyoshi.amemi
ya@ibm.com |Date: Fri, 22 Aug 2014 08:21:04 +0000 (UTC)N=From: MAILER-DAEMON@cloudband-be.local (Mail Delivery System)N,Subject: Und
elivered Mail Returned to Sender
我看了一下,我看了一下出错的原因是因为输入的源文件中有三个Date。
[root@cloudband-be E]# strings E9C79540610 |grep -c "Date"
3
能不能只处理最靠近Username的那个?
我用您的grep命令的部分可以得到以下结果。
  1. [root@cloudband-be deferred]# strings */*|grep -Po 'Username:.*(?=N)|E-mail:.*(?=N)|Password:.*(?=N)|Date:.*(?=N)'
  2. Date: Fri, 22 Aug 2014 00:53:55 +0000 (UTC)
  3. Username:       test
  4. E-mail: test@test.com
  5. Password: NVuUCIgb
  6. Date: Fri, 22 Aug 2014 00:56:13 +0000 (UTC)N=From: MAILER-DAEMON@cloudband-be.local (Mail Delivery System)N,Subject: Undelivered Mail Returned to Sender
  7. Date: Fri, 22 Aug 2014 00:56:00 +0000 (UTC)
  8. Date: Fri, 22 Aug 2014 00:56:00 +0000 (UTC)
  9. Username:       kamemiya N$E-mail:  kiyoshi.amemiya@ibm.com
  10. Password: qyBe0Qwm
  11. Date: Sat, 23 Aug 2014 06:32:49 +0000 (UTC)N=From: MAILER-DAEMON@cloudband-be.local (Mail Delivery System)N,Subject: Undelivered Mail Returned to Sender
  12. Date: Mon, 18 Aug 2014 05:36:18 +0000 (UTC)
  13. Date: Mon, 18 Aug 2014 05:36:18 +0000 (UTC)
  14. Username:       demo
  15. E-mail: demo.taro@demo.com
  16. Password: A4qMoHko
  17. Date: Fri, 22 Aug 2014 08:21:04 +0000 (UTC)N=From: MAILER-DAEMON@cloudband-be.local (Mail Delivery System)N,Subject: Undelivered Mail Returned to Sender
  18. Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)
  19. Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)
  20. Username:       kamemiya N$E-mail:  kiyoshi.amemiya@ibm.com
  21. Password: fpMMduNF
复制代码
然后应该如何处理,可以得到以下结果呢?
  1. Username: test |E-mail: test@test.com |Password: NVuUCIgb |Date: Fri, 22 Aug 2014 00:53:55 +0000 (UTC)
  2. Username: kamemiya |E-mail: kiyoshi.amemiya@ibm.com |Password: qyBe0Qwm |Date: Fri, 22 Aug 2014 00:56:00 +0000 (UTC)
  3. Username: demo |E-mail: demo.taro@demo.com |Password: A4qMoHko |Date: Mon, 18 Aug 2014 05:36:18 +0000 (UTC)
  4. Username: kamemiya |E-mail:  kiyoshi.amemiya@ibm.com |Password: fpMMduNF |Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)
复制代码
谢谢。

回复 7# MeRcy_PM


   
作者: blackold    时间: 2014-08-23 14:34
  1. awk -v OFS="|" -v FPAT='(Date|Username|Password|E-mail):[^N]*' '{for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}' urfile
复制代码

作者: bikkuri    时间: 2014-08-23 15:23
本帖最后由 bikkuri 于 2014-08-23 15:30 编辑

谢谢您的答复。
但是好像执行后出错。
  1. [root@cloudband-be E]# strings E9C79540610 |awk -v OFS="|" -v FPAT='(Date|Username|Password|E-mail):[^N]*' '{for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}'
  2. awk: {for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}
  3. awk:                              ^ syntax error
  4. awk: {for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}
  5. awk:                                          ^ syntax error
  6. awk: {for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}
  7. awk:                                                                      ^ syntax error
  8. awk: {for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}
  9. awk:                                                                                                 ^ syntax error
  10. awk: {for(i=1;i<=NF;i++)switch($i){case /Date/: d=$i;break;case /Username/:u=$i;break;case /Password/: p=$i;break;case /E-mail/: e=$i;} }END{print u,e,p,d}
  11. awk:                                                                                                                           ^ syntax error
  12. [root@cloudband-be E]#
复制代码
blackold 发表于 2014-08-23 14:34

作者: blackold    时间: 2014-08-23 15:28
回复 10# bikkuri


    可能是 awk 版本问题。我的是 GNU Awk 4.1.1,
作者: bikkuri    时间: 2014-08-23 15:36
本帖最后由 bikkuri 于 2014-08-23 16:43 编辑

我的版本是3.1.7。
  1. [root@cloudband-be E]# awk --version
  2. GNU Awk 3.1.7
  3. Copyright (C) 1989, 1991-2009 Free Software Foundation.
复制代码
可能是编译的时候没有加--enable-switch选项,所以不支持switch语句。
       If gawk is configured with the --enable-switch option to the configure command, then it accepts  an  additional
       control-flow statement:
              switch (expression) {
              case value|regex : statement
              ...
              [ default: statement ]
              }

       If gawk is configured with the --disable-directories-fatal option, then it will silently skip directories named
       on the command line.  Otherwise, it will do so only if invoked with the --traditional option.



http://stackoverflow.com/questions/11401979/switch-case-doesnt-work-in-awk


用if语句替换掉switch语句后没有出错了,但是输出的结果不正确。
  1. [root@cloudband-be E]# strings E9C79540610 |awk -v OFS="|" -v FPAT='(Date|Username|Password|E-mail):[^N]*' '{for(i=1;i<=NF;i++){if (
  2. $i~/Date/){d=$i;break;}if ($i~/Username/){u=$i;break;}if ($i~/Password/){p=$i;break;}if ($i~/E-mail/)e=$i;}}END{print u,e,p,d}'
  3. Username:||Password:|(UTC)N+Date:
复制代码
  1. [root@cloudband-be E]# strings E9C79540610 |awk -v OFS="|" -v FPAT='(Date|Username|Password|E-mail):[^N]*' '{for(i=1;i<=NF;i++){if (
  2. $i~/Date/){d=$0;break;}if ($i~/Username/){u=$0;break;}if ($i~/Password/){p=$0;break;}if ($i~/E-mail/)e=$0;}}END{print u,e,p,d}'
  3. Username:   kamemiya N$E-mail: kiyoshi.amemiya@ibm.com N||Password: fpMMduNF N|N!Return-Path: <foo@cloud-band.com>N9Received: from c
  4. loudband-be.local (localhost [127.0.0.1])N:     by cloudband-be.local (Postfix) with ESMTP id 571345405FANI     for <kiyoshi.amemiya
  5. @ibm.com>; Fri, 22 Aug 2014 08:21:01 +0000 (UTC)N+Date: Fri, 22 Aug 2014 08:21:01 +0000 (UTC)N
复制代码
看来FPAT也没起作用。
好像FPAT只适用于GNU awk 4 以上版本。



blackold 发表于 2014-08-23 15:28
回复 10# bikkuri

作者: Herowinter    时间: 2014-08-23 17:21
回复 12# bikkuri

awk 3.x没FPAT.
作者: blackold    时间: 2014-08-23 17:54
可以用 match 来匹配。
作者: bikkuri    时间: 2014-08-23 18:07
怎么做啊?大神教教我,我不会啊。。。

blackold 发表于 2014-08-23 17:54
可以用 match 来匹配。

作者: blackold    时间: 2014-08-24 09:35
回复 15# bikkuri


    自己整整啊,try:
  1. awk -v OFS="|" 'match($0,/(Date|Username|Password|E-mail):[^N]*/,a){r[substr(a[0],1,1)]=a[0]}END{print r["U"],r["E"],r["P"],r["D"]}' urfile
复制代码

作者: bikkuri    时间: 2014-08-24 12:12
谢谢您的指点,您的命令在大多数情况下是可以得到正常输出的,但是碰到了以下一个特殊情况,没有得到正确的输出:
对于源输入中的Password: NVuUCIgb N您的匹配代码match($0,/(Date|Username|Password):[^N]*/,a)在碰到密码中的第一个N字符就当作匹配结束了,所以输出成了:
  1. [root@cloudband-be D]# strings D04E354046A |awk -v OFS="|" 'match($0,/(Date|Username|Password):[^N]*/,a){r[substr(a[0],1,1)]=a[0]}END{print r["U"],r["P"],r["D"]}'
  2. Username:       test |Password: |Date: Fri, 22 Aug 2014 00:53:55 +0000 (UTC)
复制代码
这个正则表达式应该怎么改呢?

回复 16# blackold


   
作者: blackold    时间: 2014-08-24 13:53
  1. $ awk -v OFS="|" 'match($0,/(Date:[^)]*\))|(Username|Password|E-mail): *[^ ]*/,a){r[substr(a[0],1,1)]=a[0]}END{print r["U"],r["E"],r["P"],r["D"]}' urfile
复制代码

作者: Herowinter    时间: 2014-08-24 14:28
黑哥出手,分分钟搞定的事。
作者: bikkuri    时间: 2014-08-24 15:30
本帖最后由 bikkuri 于 2014-08-24 17:00 编辑

这次彻底可以了!
非常感谢!
但是还有另外一个小问题,能请您帮忙看一下这个帖子吗?
http://bbs.chinaunix.net/thread-4151599-1-1.html

回复 18# blackold


   




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2