如何提取与{START} .. <xyz> .. {END}匹配的文件的内容,但它应包含xyz

时间:2017-06-29 05:48:44

标签: python awk sed

我有一个包含以下内容的文件:

{START}
..
<xyz>
..
{END}
{START}
...
xyz
...
...
{END}
{START}
...
...
...
{END}

我需要与{START}{END}匹配且包含xyz

的内容

我已尝试过以下内容,但它似乎无法正常工作,对此的任何帮助都将受到赞赏!!

sed '/{START}/xyz/{END}/!d' run.txt
sed '/{START}/,/{END}/!d' run.txt 

这最后一个命令有效,但它提供了所有匹配{START}{END}

awk '/{START}/{p=1};/xyz/p; /{END}/ {p=0}' run.txt

我也尝试过使用正则表达式,但也无法继续使用正则表达式:

v=re.findall(r'{START}(.*xyz){END}',response,re.DOTALL)

编辑:

如果开始和结束标记相同,例如,它将如何工作?

    !
    ...
    xyz
    ...
    !
    ...
    ...
    ...
    !
    ..
    <xyz>
    ..
    !

3 个答案:

答案 0 :(得分:0)

$ awk ' 
    /{START}/{p=1} 
    /xyz/ && p==1{p+=1}
    p>0{str==""?str=$0:str=str"\n"$0}
    /{END}/ && p==2{p=0;print str;str=""}
' run.txt

输出结果为:

{START}
..
<xyz>
..
{END}
{START}
...
xyz
...
...
{END}

简要说明:

  • 使用p作为标记来区分是否找到了STARTxyzEND
  • 如果找到{START},请设置p=1
  • 如果找到xyz并且只有p==1,请设置标记p+=1
  • 如果p>0$0记录为str
  • ,则每行
  • 如果找到最终str,请打印{END},同时重置pstr

对于新请求,请将STARTEND设置为相同的模式。这是方法,

$ awk 'START{p=0}
    /!/{p+=1}
    /xyz/{q=1}
    p>0{str==""?str=$0:str=str"\n"$0}
    p==2{if(q==1){print str;q=0}str="";p=1}
' run_2.txt
!
...
xyz
...
!
..
<xyz>
..
!

答案 1 :(得分:0)

你可以像这样做Python:

with open('path_to_file', 'r') as f:
    txt = f.read()
    split_start = txt.split('{START}')
    split_start = filter(bool, split_start)
    split_end = [i.strip('{END}') for i in split_start]
    results = filter(lambda x: 'xyz' in x, split_end)

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed -n '/{START}/{:a;N;/{END}/!ba;/xyz/p}' file

{START}{END}之间收集行,如果字符串包含xyz,则打印它们。

如果分隔符使用相同:

sed -n '/!/{:a;x;/xyz/p;x;h;:b;n;/!/ba;H;bb}' file

这使用保留空间(HS)收集分隔符之间的行,并在包含所需字符串时打印HS。