如何检查多个条件,这些条件涉及变量大小的多行块,并返回主要行。

4

基本上我的文本文件看起来像这样。

 **A: lorem ipsum verade(unique)**
 a: asd
 b: asd

 c: alsd
 d: def

**B: korem ipsum vladmir(unique)**
 c: fdh
 e: asd

**C: lorum ipsum vladmir(unique)**
 a: asd
 b: asd

 d: def
 e: asd

如您所见,假设example.txt有三个主要条目(A、B、C),每个条目都有多个数据。

我的问题是,如果我想检查A的多个条件,例如我想要A、B、C中所有条目,如果a:asd和d:def。那么输出应该是A和C。

基本上,我想知道如何在跟踪先前行的同时检查多行。

希望我表达清楚了。请记住,这是一个巨大的文件,因此如果可能的话,请避免多次循环。


你如何确定什么是“主入口”?大写字符后跟冒号吗?其他条目是否总是以<小写字符><冒号><空格><值><EOL>格式呈现? - zwer
是的,可以使用特定的关键字来实现这个目的。 - akshay kumar
你期望的输出是什么?只有你的例子中的 A&C 吗? - CWLiu
是的,那就足够了。 - akshay kumar
5个回答

1
在AWK中:
  1. 你应该将主入口的所有行存储在一个数组中。
  2. 对于每个检查过的行,如果出现a:asd或d:def,则将变量(假设为“计数器”)加1。
  3. 如果遇到新的主入口并且计数器等于2,则打印数组,然后清除计数器和数组。

但是在这种情况下的问题是,如果有多个相同的条目,则计数器也会增加,但我想要精确匹配,例如两个参数a和d都应该存在... - akshay kumar
所以创建两个“计数器”,一个用于参数 a,另一个用于参数 b。 - JUSHJUSH

0
如果要搜索的字符串分别被赋值为“v1”和“v2”,则:
$ v2="a: asd"; v1="d: def"
$ awk -v v1="$v1" -v v2="$v2" '/\*\*.*\*\*/{s=substr($0,match($0,/\*\*.\:/)+2,1);next}{a[s]=a[s] $0}END{for(i in a)if(match(a[i],v1)&&match(a[i],v2))print i}' test.txt
A
C

这个一行代码可以扩展为以下代码块:

$ cat awk-script
/\*\*.*\*\*/{
  s=substr($0,match($0,/\*\*.\:/)+2,1);
  next
}
{
  a[s]=a[s] $0
}
END{
  for(i in a)
    if(match(a[i],v1)&&match(a[i],v2))
      print i
}

$ awk -v v1="$v1" -v v2="$v2" -f awk-script test.txt
A
C

简要说明:

  • /\*\*.*\*\*/:查找主要条目
  • s=substr($0,match($0,/\*\*.\:/)+2,1):将主要条目的值赋给's'
  • a[s]=a[s] $0:将属于每个主要条目的记录分配给它们
  • match(a[i],v1)&&match(a[i],v2):检查'v1'和'v2'是否与每个主要条目中的值匹配。

0
这可能适用于您(GNU sed):
sed '/^\s*\*\*/{:a;x;//!bb;/a: asd/!bb;/d: def/!bb;p;:b;x;h;d};H;$!d;ba' file

在保留空间中存储多行集合。在开始新的集合之前,请检查保留空间并打印出符合要求的内容。在文件末尾最后一次检查保留空间。

集合的开始由以**(或带有一些前导空格的**)开头的行表示。为了打印集合,它必须包含字符串a: asdd: def,否则它是一个错误的集合,最好忘记它。所有其他行都可以附加到当前集合。


0

使用Python:

创建一个空列表来存储选定的块: blocks=[]

创建标志以记录是否找到模式('asd','def') s_asd,s_def=False,False

为当前块创建一个空列表: blck=[]

逐行读取并检查它们: 如果该行包含 ** 并且 s_asd、s_def 为 True,则将当前块附加到 'blocks'。 清除当前块('blck'),并将标志设置为 False。 如果该行不包含 **,则检查 'asd' 或 'def' 模式并设置相应的标志。 将当前行附加到 'blck'。

在循环结束时,必须再次检查标志,并在必要时将 'blck' 附加到 'blocks'。

代码示例:

...
line=line.strip()
if line[:2]=="**" and line[-2:]=="**":
   if s_asd and s_def:
       blocks.append(blck)
       s_asd,s_def=False,False
   blck=[]
...

0
$ cat tst.awk
match($0,/[[:upper:]]:/) { prt(); key=substr($0,RSTART,1) }
{ rec = rec $0 ORS }
END { prt() }
function prt() {
    if ( (rec ~ /a: asd/) && (rec ~ /d: def/) ) {
        print key
    }
    rec = key = ""
}

$ awk -f tst.awk file
A
C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接