2017-09-01 34 views
1

我正在解析大量文件并搜索awk的对应关系。 我被困在寻找一种方法来查找包含pattern1和搜索pattern2只在这个文件中的文件。awk:在包含pattern2的文件中找到匹配的pattern1

例如:

file1: 
text xyz 122e345a rxyc 
abc 25b57790c 

file 2: 
text tio 36e79a89 opgb 
abc b0894e35o 

file 3: 
text diowps aaaacc 
abc 122e345a 

我想要什么作为的结果应该是:

25b57790c 

虽然,我有第一种模式是:

122e345a 

唯一的解决办法我有现在是分两步来做:

FILE=$(awk '$3 == "122e345a" {print FILENAME}' *) 
awk '$1 == "abc" {print $2}' $FILE 

我可以有一个衬垫像这样的:

awk '$1 == "abc" {print $2}' $(awk '$3 == "122e345a" {print FILENAME}' *) 

但我想,以避免双重AWK通话,不能把它在一个单一的awk命令来实现?

+0

一个优秀的第一Q.保持张贴! (但是*在每行代码/数据/错误消息的前面使用4个空格,或者突出显示一段文本,并使用编辑框左上角的格式化工具将代码/数据/输出格式化*。祝你好运 – shellter

+0

“模式”这个词是不明确的,应该避免,为了澄清你的问题 - 无论它出现在什么地方,用“字符串”或“正则表达式”替换“模式” ,并说明匹配应该是完整的还是部分的,它从你的脚本中看到,比如你想要做的是在完整的字符串上进行字符串匹配,但是我们不能确定你想从脚本中得到什么,你现在有2个答案 - 一个使用完整的字符串匹配和另一个部分正则表达式匹配,所以它可以节省时间,如果你只是说明你真正需要的。 –

回答

2
file != FILENAME  { found = 0 } 
     $3 == a  { found = 1; file = FILENAME } 
found && $1 == b  { print $2 } 

,或者对于GNU awk

BEGINFILE    { found = 0 } 
     $3 == a  { found = 1 } 
found && $1 == b  { print $2 } 

这是非常相似的markp的解决方案(并使得类似的假设),但可以在任意数量的输入文件,不使用外壳来运行循环:

$ awk -f script.awk a="122e345a" b="abc" file[123] 
25b57790c 

脚本还假定您想要搜索的模式实际上是固定在特定列中的字符串(如问题所示)。

由于没有在awk“倒带”文件的方式,你需要,如果你想第一个字符串之前找到第二个字符串越过文件两次。问题最后的代码本身就是一个解决方案。

或者,您可以将整个文件保存在一个变量中,并在找到第一个字符串(该解决方案未包括在此处)时检查该文件。

+0

第一个脚本没有给出结果,第二个脚本没有按预期工作。 当模式b与正确的文件解析后的所有文件匹配时,它会打印第二个参数,该文件不包括在内。 – luxfred

+1

@luxfred然后,您要么将问题描述出来,要么无法正确运行脚本。这两个脚本都可以与GNU Awk一起工作,而第一个脚本可以与GNU Awk,Mawk和BSD Awk一起工作,而不管输入文件的顺序如何(问题文本中的三个文件)。 – Kusalananda

+0

我再次检查,问题是我的文件是错误的第二个模式显示在第一个拳头之前。 第二个脚本报告从匹配第一个模式的文件开始的所有文件 但第一个脚本完全是我正在寻找的技巧,谢谢 – luxfred

1

注意:已更新以显示所需图案的完整匹配;如果目标是为了显示部分匹配然后替换搜索模式相应地:

partial matching: $3 ~ /122e345a/ 
        $1 ~ /abc/ 

complete matching: $3 == "122e345a" 
        $1 == "abc" 

假设:

  • 第一搜索由寻找一个线,其中所述第三字段是一个完整的匹配对于字符串"122e345a",并且如果找到,则...
  • 查找一行,其中第一个字段与字符串​​完全匹配,并且如果找到,则...
  • 打印第二字段的内容
  • 字符串"122e345a"首先出现在文件中(包含字符串​​行)中,用表示了串​​或者a)在同一行中为第一串或b )在随后的线
  • 如果字符串​​多次显示出来在一个文件中(串"122e345a"被发现之后),则串​​每次出现将导致发出的命令print

一个可能awk溶液:

awk ' 
BEGIN       { found = 0 } 
       $3 == "122e345a" { found = 1 } 
(found == 1) && $1 == "abc"  { print $2 } 
' <file> 
  • 设置可变found=0;因为这是BEGIN块它只是在处理新的文件开始执行的部分(即,我们正在初始化found
  • 如果字符串"122e345a"在一条线上的第3场被发现然后设置found = 1
  • 如果我们的变量found设置为1,和字符串​​在一条线上的第一场被发现,然后打印该行的第二场

注意:您可以提交awk脚本作为多线构建(上图)或作为单一线,例如:

awk 'BEGIN { found = 0 } $3 == "122e345a" { found = 1 } (found == 1) && $1 == "abc" { print $2 }' <file> 

使用示例文件(file1/file2/file3),并加入file4file1与线副本切换:

$ cat file4 
abc 25b57790c 
text xyz 122e345a rxyc 

$ for f in file* 
do 
    echo "++++++++++++++ file : $f" 
    awk 'BEGIN { found = 0 } $3 == "122e345a" { found = 1 } (found == 1) && $1 == "abc" { print $2 }' $f 
done 

++++++++++++++ file : file1 
25b57790c 
++++++++++++++ file : file2 
++++++++++++++ file : file3 
++++++++++++++ file : file4 

注意到,虽然file4具有同时匹配搜索字符串线,串"122e345a"显示出来字符串​​,这违背了其中一个假设,所以file4未能通过我们的搜索。

+0

@luxfred,我不明白你的评论;你试过了吗?代码,如果是这样,它工作还是不工作? – markp

+0

这并没有' t似乎给了我任何结果。 但是,如果我只是在所有文件上尝试awk脚本,我就会得到匹配后解析的所有文件的结果。排除好结果 – luxfred

+0

$ for file in file * do echo“++++++++++++++ file:$ f” awk'BEGIN {found = 0} $ 3〜/ 122e345a/{实测值= 1}(实测== 1)&& $ 1〜/ ABC/{打印$ 2} '$ F 完成 给没有结果, 但: AWK' BEGIN {实测值= 0} $ 3〜/ 122e345a/{找到= 1}(发现== 1)&& $ 1〜/ ABC/{打印$ 2}” * 显示: b0894e35o 122e345a .... 其实我有上百个匹配相同的方案文件。 当我在所有命令上通过awk one时,匹配之前的所有文件都不显示任何内容,但之后的所有文件都显示为abc 正确的文件本身不显示任何内容 – luxfred