Bash 测试模式A和B,并返回模式A和B之间的文本行;B
大家好 我有一个非常大的平面文件,我正在寻找出口的所有记录,匹配2个不同的模式。问题在于每条记录中的行数不同,并且记录相互渗透。记录的最后一行是门ID,第一行是用户: 我正在测试电子邮件地址中的@,最后一次登录包含“登录时间:2013-08”。我需要导出所有行,包括电子邮件地址行和最后登录行。下面是两个样本。我尝试过使用awk,如下所示:Bash 测试模式A和B,并返回模式A和B之间的文本行;B,bash,awk,grep,pattern-matching,Bash,Awk,Grep,Pattern Matching,大家好 我有一个非常大的平面文件,我正在寻找出口的所有记录,匹配2个不同的模式。问题在于每条记录中的行数不同,并且记录相互渗透。记录的最后一行是门ID,第一行是用户: 我正在测试电子邮件地址中的@,最后一次登录包含“登录时间:2013-08”。我需要导出所有行,包括电子邮件地址行和最后登录行。下面是两个样本。我尝试过使用awk,如下所示: awk '/login time: 2013-08/{e=0}/@ /{gsub("^.*@ ","",$0);e=1}{if(e==1){print}}'
awk '/login time: 2013-08/{e=0}/@ /{gsub("^.*@ ","",$0);e=1}{if(e==1){print}}' filename
当然,这失败了
下面是示例数据
User: afshin@runners.org
First Name: Afshi
Last Name: Noghami
Is Delegated Admin: False
IP Whitelisted: False
Account Suspended: False
Must Change Password: False
Unique ID: 102209840259208897543
ID TPYE: Cx4
Creation Time: 2013-06-07T04:14:42.000Z
Last login time: Never
Path: /Members/Inactive
IMs:
Addresses:
Organizations:
Phones:
Relations:
Door IDs:
User: jjnalli@runners.org
First Name: JISS
Last Name: NALLIKUZHY
Is a Super Admin: False
Is Delegated Admin: False
Has Agreed to Terms: True
IP Whitelisted: False
Account Suspended: False
Must Change Password: False
Unique ID: 109765147242431344122
ID TYPE: Cx4
Mailbox setup: True
Included: False
Creation Time: 2013-06-07T03:32:52.000Z
Last login time: 2013-08-02T07:13:02.000Z
Path: /Members/Inactive
IMs:
Addresses:
Organizations:
Phones:
Relations:
Door IDs:
对于每个具有最后登录日期的记录,所需的输出如下所示:
User: jjnalli@runners.org
First Name: JISS
Last Name: NALLIKUZHY
Is a Super Admin: False
Is Delegated Admin: False
Has Agreed to Terms: True
IP Whitelisted: False
Account Suspended: False
Must Change Password: False
Unique ID: 109765147242431344122
ID TYPE: Cx4
Mailbox setup: True
Included: False
Creation Time: 2013-06-07T03:32:52.000Z
Last login time: 2013-08-02T07:13:02.000Z
也许这样的事情对你有用:
awk '$1=="User:",/login time: 2013-08/' file
也许这样的事情对你有用:
awk '$1=="User:",/login time: 2013-08/' file
将从^User
到门ID
的行分组,然后仅在匹配时打印。*登录时间:20[0-9]。。。
我想我终于明白了你的需要:
试试这个:
sed -ne '/^Door ID/!H;/^User:/h;/^Door ID/{x;G;/@.*login time: 20[0-9]/p}' file
这将符合您的要求
合并每个数据包后,您甚至可以删除与2013-08匹配的所有条目:
将从^User
到门ID
的行分组,然后仅在匹配时打印。*登录时间:20[0-9]。。。
我想我终于明白了你的需要:
试试这个:
sed -ne '/^Door ID/!H;/^User:/h;/^Door ID/{x;G;/@.*login time: 20[0-9]/p}' file
这将符合您的要求
合并每个数据包后,您甚至可以删除与2013-08匹配的所有条目:
首先,将每条记录读入字段数组:
BEGIN { FS = ": " } # each line has fieldname and value
/^$/ { next } # skip blank records
$1 == "User" { # first field of new record
delete fields # delete current array
fields[$1] = $2 } # store field value in array
$1 == "Door IDs" { # last field of current record
fields[$1] = $2 # store field value in array
do_process() } # process current record
$1 != "User" && # fields between first ...
$2 != "Door IDs" { # ... and last
fields[$1] = $2 } # store field value in array
然后,对记录做任何你需要做的事情。这里我打印用户和上次登录时间字段,但您可以执行任何需要的处理:
function do_process() {
print fields["User"], fields["Last login time"] }
请注意,我尚未测试此代码
编辑:根据下面的评论进行修改。我假设User字段总是标记新记录的开始。以下是用于读取和存储记录的代码的修订版本:
BEGIN { FS = ": " # each line has fieldname and value
first = 1 } # flag for first record
/^$/ { next } # skip blank records
$1 == "User" { # first field of new record
if (first > 1) # no data the first time; skip
do_process() # process current record
delete fields # reset fields for new record
fields[$1] = $2 } # store field value in array
$1 == "Door IDs" { # last field of current record
fields[$1] = $2 # store field value in array
do_process() } # process current record
/./ { fields[$1] = $2 } # store field value in array
END { if (first > 1) # last record not processed
do_process() } # process last record
然后,您可以随意处理数据。首先,将每条记录读入字段数组:
BEGIN { FS = ": " } # each line has fieldname and value
/^$/ { next } # skip blank records
$1 == "User" { # first field of new record
delete fields # delete current array
fields[$1] = $2 } # store field value in array
$1 == "Door IDs" { # last field of current record
fields[$1] = $2 # store field value in array
do_process() } # process current record
$1 != "User" && # fields between first ...
$2 != "Door IDs" { # ... and last
fields[$1] = $2 } # store field value in array
然后,对记录做任何你需要做的事情。这里我打印用户和上次登录时间字段,但您可以执行任何需要的处理:
function do_process() {
print fields["User"], fields["Last login time"] }
请注意,我尚未测试此代码
编辑:根据下面的评论进行修改。我假设User字段总是标记新记录的开始。以下是用于读取和存储记录的代码的修订版本:
BEGIN { FS = ": " # each line has fieldname and value
first = 1 } # flag for first record
/^$/ { next } # skip blank records
$1 == "User" { # first field of new record
if (first > 1) # no data the first time; skip
do_process() # process current record
delete fields # reset fields for new record
fields[$1] = $2 } # store field value in array
$1 == "Door IDs" { # last field of current record
fields[$1] = $2 # store field value in array
do_process() } # process current record
/./ { fields[$1] = $2 } # store field value in array
END { if (first > 1) # last record not processed
do_process() } # process last record
然后,您可以随意处理数据。您能给我们一个所需输出的示例吗?正在将所需输出添加到原始帖子中…您能给我们一个所需输出的示例吗?正在将所需输出添加到原始帖子中…不幸的是,这没有删除任何包含登录名的记录2013-08年之前。感谢您的贡献。很幸运,这并没有删除2013-08年之前包含登录名的任何记录。谢谢你的贡献谢谢你的帮助。但是我们的远程工作者没有门ID字段。。。。只有3个常用字段是上次登录、创建日期和用户:请查看上面的修改版本。感谢您的帮助。但是我们的远程工作者没有门ID字段。。。。仅有的3个常用字段是上次登录、创建日期和用户:查看上面的修改版本。感谢您的贡献,但这一行出错了。请看下面。这可能是由于在Mac上使用Apple实现awk。。。awk:源代码第1行上下文的语法错误为/User:/{if(NR!=1){for(i=0;i>>一个[i]>“file”k我在linux中测试了它,运行良好…可能与Mac不兼容:(感谢您的贡献,但这一行错误已消失。请参见下面。这可能是由于在Mac with Apple上实现awk…awk:源行1上下文的语法错误为/User://{if(NR!=1){for(i=0;i>>a[i]>“文件”k我在linux中测试了它,效果很好…可能与Mac不兼容:(