如何使用sed从文件中打印第6行,但仅当文件中的任何其他行与模式匹配时

时间:2015-06-01 20:53:57

标签: sed

并且,以更通用的方式,是否可以使用程序sed打印匹配PATTERN 1的任何行,但仅当文件中的任何其他行与PATTERN 2匹配时?它可以通过grep命令的组合来完成,但我试图用一个sed命令完成它。

5 个答案:

答案 0 :(得分:3)

这不是sed的工作:

awk 'NR==FNR{if (/PATTERN2/) f=1; next} f && (FNR==6)' file file

awk 'NR==FNR{if (/PATTERN2/) f=1; next} f && /PATTERN1/' file file

或者如果您不想两次指定文件名:

awk 'BEGIN{ARGV[ARGC]=ARGV[ARGC-1]; ARGC++} NR==FNR{if (/PATTERN2/) f=1; next} f && /PATTERN1/' file

答案 1 :(得分:2)

我相信这是可能的:

:l1 {
    /foo/ { H }
    /bar/ { x ; s/^\n//; p ; s/.*//; h ; b l2}
    n
    b l1
}

:l2 {
    /foo/ { p }
    n
    b l2
}

快速概述:

l1是我们的初始循环。它将检查/foo/(模式1)。如果在一条线上找到它,该线将被附加到持有空间。 下一行将检查/bar/,找到后,它将交换保留空间和模式空间(x),从数据中删除初始换行符(这是因为我们使用H在我们的第一行中,我们p对数据进行了处理,我们将这些数据清空并将其存回到保持模式中(因此它将为空)。然后,我们bl2进行搜索实际上,离开循环l2

如果该行与模式1 foo或模式2 bar不匹配,则会转到下一行,然后再次跳回到开始l1

我们进入l2后,检查模式1 /foo/。既然我们知道我们之前已经找到了模式2(否则我们不会在这里),我们可以安全地打印这些数据。如果不是foo,我们只是跳过那一行,然后循环回到l2的开头。

使用以下数据进行了相当多的测试:

a
b
c foo
d
e foo
f bar
g foo
h
i foo
j
k

根据“bar”的不同,它会打印foo的所有行,或者根本不打印任何行。

当然,它不会赢得任何选美比赛,但它只是用sed写的。

答案 2 :(得分:1)

这是一个sed脚本,可以打印匹配pattern1的行,如果存在匹配pattern2的行,则无论pattern1的顺序如何,pattern2:

#n
:loop 
    /foo/H
    /bar/{      
        g
        s/\n//
        /foo/p          
        :loop2 
            n
            /foo/p              
            b loop2         
    }
    n
    b loop

如果将其保存到s.sed等文件中,则可以执行

sed -f s.sed file

#n与-n的工作方式相同,意味着抑制标准输出。 loop将与foo(pattern1)匹配的任何行追加到保留空间。遇到bar(pattern2)时,它会使用g命令获取保留空间的内容(擦除当前模式空间)。它删除了第一个新行(即使保留空间为空,H命令也会添加一个新行)。如果它包含foo(意味着它不是空的),它会打印出模式空间。然后n转到下一行。现在我们已匹配pattern2,我们可以通过启动loop2

安全地打印foo的所有匹配项

答案 3 :(得分:1)

这可能适合你(GNU sed):

sed -n ':a;6H;/pattern/{z;H};n;$!ba;x;s/\n//;s///p' file

使用选项-n关闭图案空间的自动打印。设置一个循环,该循环读取文件的每一行,并在保留空间中附加单行(对于第6行)和/或(不)空行(表示在pattern上发生匹配)。在文件交换到保留空间的末尾,删除永远存在的第一个换行符(如果已追加行或空行)并删除第二个换行符并在成功时打印结果。

N.B。如果文件中存在pattern,则保留空间将包含两个换行符,前两个字符或第一个和最后一个字符。

答案 4 :(得分:0)

如果不解析文件两次,一般情况下无法做到这一点。这意味着两次调用sed

如果匹配“触发模式”的行总是在所有匹配“匹配模式”的行出现之后发生,那么这可能会为您执行此操作:

$ cat testdata
1 aaa
2 match
3 match
4 ddd
5 trigger (only print line 2 and 3 if this line is present)

$ sed -n -e '/match/H' -e '/trigger/{x;^Mp;^M;q^M}' testdata

2 match
3 match

^M有逐字换行符)

我不确定如何删除输出中的初始空行。关于这一点的指针受到欢迎。

更新:我在命令序列的末尾为“触发模式”放置了最后的q(退出),以确保文件中稍后的其他触发模式不会搞砸输出。