Bash 提取两个图案之间的线条,并使用if条件删除线条之间的线条

Bash 提取两个图案之间的线条,并使用if条件删除线条之间的线条,bash,shell,awk,sed,Bash,Shell,Awk,Sed,我有一个包含以下内容的文件。我试图提取具有匹配的开始和结束模式的块,在这两者之间,我想排除具有不匹配的数字id(可能是模式)的块。此处必须排除[001]以外的内容。002可能不知道。因此,我只希望块与[001]匹配 文件包含: text [001] start line 1 line 2 text [002] mid start line 3 line 4 text [002] mid end line 5 lin

我有一个包含以下内容的文件。我试图提取具有匹配的开始和结束模式的块,在这两者之间,我想排除具有不匹配的数字id(可能是模式)的块。此处必须排除[001]以外的内容。002可能不知道。因此,我只希望块与[001]匹配

文件包含:

    text [001] start
    line 1
    line 2
    text [002] mid start
    line 3     
    line 4
    text [002] mid end
    line 5
    line 6
    text [001] end
我需要块,不包括不匹配的数字id[002]的块

    text [001] start
    line 1
    line 2
    line 5
    line 6
    text [001] end
对于这个问题,我无法在互联网上得到明确的澄清。有人能帮助我们解决这个问题吗,awk或sed解决方案

要获得具有开始和结束模式的块,我尝试使用

   awk '/[001]/ && /start/, /001/ && /end/' File
使用sed或Perl:

sed '/001.*start/,/001.*end/!d;/002.*start/,/002.*end/d'

perl -ne 'print if /001.*start/ .. /001.*end/
                and not /002.*start/ .. /002.*end/'
使用前瞻断言可以轻松地使排除的标记动态化:

perl -ne 'print if /001.*start/ .. /001.*end/
                and not /text \[(?!001).*start/ .. /text \[(?!001).*end/'
使用sed或Perl:

sed '/001.*start/,/001.*end/!d;/002.*start/,/002.*end/d'

perl -ne 'print if /001.*start/ .. /001.*end/
                and not /002.*start/ .. /002.*end/'
使用前瞻断言可以轻松地使排除的标记动态化:

perl -ne 'print if /001.*start/ .. /001.*end/
                and not /text \[(?!001).*start/ .. /text \[(?!001).*end/'

这个
awk
可以。您可能需要调整触发器以处理数据:

awk '/\[001\] start/{f=1} /\[002\] .* start/{f=0} f;  /\[001\] end/{f=0}  /\[002\] .* end/{f=1}' file
    text [001] start
    line 1
    line 2
    line 5
    line 6
    text [001] end
可读性更强

awk '
    /\[001\].*start/ {f=1}
    /\[002\].*start/ {f=0} 
    f;  
    /\[001\].*end/ {f=0}
    /\[002\].*end/ {f=1}
    ' file

只需更改触发器代码以反映真实数据。

awk
可能就可以了。您可能需要调整触发器以处理数据:

awk '/\[001\] start/{f=1} /\[002\] .* start/{f=0} f;  /\[001\] end/{f=0}  /\[002\] .* end/{f=1}' file
    text [001] start
    line 1
    line 2
    line 5
    line 6
    text [001] end
可读性更强

awk '
    /\[001\].*start/ {f=1}
    /\[002\].*start/ {f=0} 
    f;  
    /\[001\].*end/ {f=0}
    /\[002\].*end/ {f=1}
    ' file

只需更改触发代码以反映真实数据。

假设我们使用变量
b1
(如果我们在块1中)和
b2
(如果我们在块2中):

awk '/001/ && /start/ { b1=1 }
     /002/ && /start/ { b2=1 }
     (b1 && !b2)
     /002/ && /end/   { b2=0 }
     /001/ && /end/   { b1=0 }' file

范围表达式很方便,但请记住:永远不要使用范围表达式(例如,
/start/,/end/
)因为它们使琐碎的任务变得非常简短,但随后需要重复的条件或对最微小的需求更改进行完全重写。

假设我们使用变量
b1
(如果我们在块1中)和
b2
(如果我们在块2中):

awk '/001/ && /start/ { b1=1 }
     /002/ && /start/ { b2=1 }
     (b1 && !b2)
     /002/ && /end/   { b2=0 }
     /001/ && /end/   { b1=0 }' file

范围表达式很方便,但请引述:永远不要使用范围表达式(例如,
/start/,/end/
),因为它们使琐碎的任务变得非常简单,但随后需要重复的条件或完全重写以满足最微小的需求更改。

假设您的块嵌套到任何深度,并且从不重叠:

$ cat tst.awk
BEGIN { tgtId="001" }

match($0,/\[[0-9]+\]/) {
    id = substr($0,RSTART+1,RLENGTH-2)
    state = $NF
}

state == "start"  { isTgtBlock[++depth] = (id == tgtId ? 1 : 0) }

isTgtBlock[depth] { print }

state == "end"    { --depth }

{ id = state = "" }

$ awk -f tst.awk file
    text [001] start
    line 1
    line 2
    line 5
    line 6
    text [001] end

假设块嵌套到任意深度,并且从不重叠:

$ cat tst.awk
BEGIN { tgtId="001" }

match($0,/\[[0-9]+\]/) {
    id = substr($0,RSTART+1,RLENGTH-2)
    state = $NF
}

state == "start"  { isTgtBlock[++depth] = (id == tgtId ? 1 : 0) }

isTgtBlock[depth] { print }

state == "end"    { --depth }

{ id = state = "" }

$ awk -f tst.awk file
    text [001] start
    line 1
    line 2
    line 5
    line 6
    text [001] end
这可能适用于您(GNU-sed):

仅打印
[001]
分隔符之间的行,并排除
[002]
分隔符之间的行。

这可能适用于您(GNU-sed):



仅打印
[001]
分隔符之间的行,并排除
[002]
分隔符之间的行。

如何找到001块,您假设只删除002块。啊哈!非代表性样本输入。它写在OPs post中:
我试图提取具有匹配开始和结束模式的块
。这将被更新。也许我对“提取”的理解太宽泛了。你能建议一个适用于任何其他内部块的解决方案吗?。这里可能会有所不同。所以,我需要移除001以外的块。表示,以002为模式可能不适合@如何找到001块,假设只需要删除002块。啊哈!非代表性样本输入。它写在OPs post中:
我试图提取具有匹配开始和结束模式的块
。这将被更新。也许我对“提取”的理解太宽泛了。你能建议一个适用于任何其他内部块的解决方案吗?。这里可能会有所不同。所以,我需要移除001以外的块。表示,以002为模式可能不适合@如果001和002的角色颠倒了怎么办?@kvantour我想这只是一个示例代码。他需要一个数据块,在该块中有一些东西需要删除。我认为除了
001
之外的任何数字都可以出现在该块中,并且这些“子块”应该被删除。而不是子块,它可能被称为位于某个块中的具有不匹配数字id的块。这里001是需要的块,002是不匹配的块@WiktorStribiżew@Megkcalb所以答案中没有一个对你有帮助。不给予+1或接受1?如果001和002的角色颠倒了怎么办?@kvantour我想这只是一个示例代码。他需要一个数据块,在该块中有一些东西需要删除。我认为除了
001
之外的任何数字都可以出现在该块中,并且这些“子块”应该被删除。而不是子块,它可能被称为位于某个块中的具有不匹配数字id的块。这里001是需要的块,002是不匹配的块@WiktorStribiżew@Megkcalb所以答案中没有一个对你有帮助。不给出+1或接受+1?如果块002在块001之后结束怎么办。您和min都将在重叠块中失败。。。迷人的。这将仍然打印块1中不属于块2的所有内容。如果块002在块001之后结束,该怎么办。您和min都将在重叠块中失败。。。迷人的。这将仍然打印块1中不属于块2的所有内容。