使用sed提取以特定模式开头的行

我的输入文件是这样的:
IDno="1"
Name=Jack
Type=Student
IDno="2"
Name=Jill
Type=Teacher

我正在使用sed命令提取所有ID号和类型,只有当类型为学生时。
sed -e '/IDno=/b' -e '/Type=Student/b' d

这会给我所有类型为学生的行,但不包括ID号码。
我想要获取。
IDno="1"
Type=Student
IDno="2"

但是我正在变得更好
Type=Student

我做错了什么?

egrep不是更简单吗?egrep -e "IDno=|Type=Student" inputfile - Terrance
1你是不是想写-e d(而不仅仅是d)?否则这个命令就是格式错误的。不过,更加符合惯用法的做法是使用!来颠倒逻辑,而不是通过跳过d字符,即 sed '/IDno=\|Type=Student/!d' - steeldriver
4个回答

使用sed命令打印特定行时,可以更方便地使用-n选项和p命令。
sed -rn '/IDno=|Type=Student/p'

或者:

sed -n -e '/IDno=/p' -e '/Type=Student/p'

-n选项抑制输出,除非显式打印。当然,p命令会打印匹配的行。


egrep可以从文件中获取多行内容。使用管道符号|作为分隔符,您可以提取任意数量的不同条件。 egrep相当于grep -Eegrep是在/bin文件夹中找到的一个脚本,其内容指向exec grep -E "$@"

示例:

egrep "IDno=|Type=Student" inputfile

或者

grep -E "IDno=|Type=Student" inputfile

应输出:
IDno="1"
Type=Student
IDno="2"

希望这能帮到你!

2egrep已经被grep -E取代,是时候摆脱陈词滥调了... - heemayl
这个会返回每一行中包含"IDno="的内容,无论下面两行是否有"Type=Student"。原始问题似乎是只返回"Student"的IDno,但是提问者好像喜欢这样,所以...? - Xen2050
这样做很好,再将其传回grep只返回ID和类型行,就可以同时去掉名称(以及--分隔线),就像添加|grep "IDno=\|Type="一样。 - Xen2050
@heemayl 说得好!=)习惯难改,我猜可能有一天他们会移除这个脚本,但据我了解,它还保留在那里是为了不修改依赖于它的旧应用程序。 - Terrance

  • awk:

    将字段分隔符设置为=,并打印包含Type=Student作为整个记录或IDno作为第一个字段的记录:

    awk -F= '$1=="IDno" || $0=="Type=Student"'
    
  • perl:

    打印以IDno开头后跟=的行,或以Type开头,后跟=并以Student结尾的行:

    perl -ne 'print if /^(IDno=|Type=Student$)/'
    

例子:

% cat file.txt                                  
IDno="1"
Name=Jack
Type=Student
IDno="2"
Name=Jill
Type=Teacher

% awk -F= '$1=="IDno" || $0=="Type=Student"' file.txt
IDno="1"
Type=Student
IDno="2"

% perl -ne 'print if /^(IDno=|Type=Student$)/' file.txt
IDno="1"
Type=Student
IDno="2"

原始问题似乎是在询问“只有当类型为学生时,提取所有的ID号和类型”。但是示例输出返回了所有ID号=行,这有些矛盾...
下面是一个只返回ID号和类型为学生的答案。
sed -n 'N;N;/IDno=.*Type=Student/p' filename | grep -v "^Name="

一点解释:
- -n, --quiet, --silent 抑制自动打印模式空间 - N;N; 读取/附加下一行输入到模式空间中(两次) - /IDno=.*Type=Student/p 查找并打印从IDno=到Type=Student的内容 - | grep -v "^Name=" 不显示Name=行
我不喜欢sed|grep,但是不太确定如何让sed重新搜索其输出,而且管道通常表示“获取此输出并执行某些操作”...也可以使用grep|sed。
grep -v "^Name=" t | sed -n 'N;N;/IDno=.*Type=Student/p'

这个例子的输出解释了那个。 - muru
@muru 谢谢,我也刚注意到了,感觉描述或示例输出中可能有错误。实际上,我在我的回答中也发现了一个错误,将名称粘贴在ID之后...也许有人会发现这个答案还是有用的(尤其是在我修复之后),我仍然从中学习着。 - Xen2050
2读作:"(所有的ID号)和(只有当类型是学生时才显示类型)" - muru