Python 如何检查属于可变大小行块的多行上的多个条件并返回主线

Python 如何检查属于可变大小行块的多行上的多个条件并返回主线,python,python-3.x,awk,sed,Python,Python 3.x,Awk,Sed,基本上我的文本文件是这样的 **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有3个主要条目(A、B、C),其中包含多个数据。 我的

基本上我的文本文件是这样的

 **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有3个主要条目(A、B、C),其中包含多个数据。 我的问题是,如果A:asd和d:def,我可以检查A的多个条件吗?例如,我想要A、B、C的所有条目。所以输出应该是A和C。 基本上,我想知道如何检查多条线路,同时提前跟踪线路。 我希望我说得很清楚。请记住这是一个巨大的文件,因此如果可能,需要避免多次循环。

在AWK中:

  • 您应该将主条目中的所有行存储在一个数组中
  • 对于a:asd或d:def向变量添加1的每个选中行(比如“计数器”)
  • 若遇到新的主条目打印数组,若计数器等于2,则清除计数器和数组

  • 如果要搜索的字符串分别分配给“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”是否与每个主条目中的值匹配
    这可能适合您(GNU-sed):

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

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

    使用python:

    创建空列表以存储选定的块: 块=[]

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

    为当前块创建empy列表: blck=[]

    逐行阅读并检查: 如果行包含**和s_asd,s_def为真,则将当前块附加到“块”中。 然后清除当前块('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=[]
    ...
    

    您如何确定主条目是什么?大写字符后跟冒号?其他条目是否总是采用
    格式?是的,可用于此目的或特定关键字。您预期的输出是什么?仅以A&C为例?是的,这就足够了。但这种情况下的问题是,如果这里有多个相同的条目,那么计数器也会增加,但我希望精确匹配,就像参数A和d都应该在那里一样……因此,为参数A和参数b创建两个“计数器”
    ...
    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=[]
    ...
    
    $ 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