使用awk简化文本处理管道

使用awk简化文本处理管道,awk,sed,Awk,Sed,我有以下文本数据(高度简化): 所需输出为: dn: cn=kerberos,cn=schema,cn=config objectClass: olcSchemaConfig cn: kerberos some: properties 为此,我编写了以下shell管道: awk -vRS= -vFS="\n" '/kerberos/{print $0}' /tmp/input.txt | \ sed 's/{0}kerberos/kerberos/' | \ sed '/som

我有以下文本数据(高度简化):

所需输出为:

dn: cn=kerberos,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: kerberos
some: properties
为此,我编写了以下shell管道:

awk -vRS= -vFS="\n" '/kerberos/{print $0}' /tmp/input.txt | \
    sed 's/{0}kerberos/kerberos/' | \
    sed '/some: junk/,$d'

这很好,但我觉得混合awk和sed是“作弊”。如何使用单个awk脚本实现此功能?

显然,您只需要一个
sed
命令,而不是两个:

sed -e 's/{0}kerberos/kerberos/' -e '/some: junk/,$d'
除非您坚持使用C shell,否则行末尾的反斜杠是不必要的

您可以在一个
sed
命令中完成这一切:

sed -n -e '/kerberos/,/^$/{
        s/{0}kerberos/kerberos/
        /some: junk/,$d; p;}' 
可以在
s//
替换后用分号将其展平到一行

sed -n -e '/kerberos/,/^$/{ s/{0}kerberos/kerberos/; /some: junk/,$d; p; }' 
Mac OS X(BSD)上的
sed
需要
}
前面的分号;GNU
sed
没有它是幸福的

您也可以在
awk
中完成这一切:

awk '/kerberos/,/^$/ { sub(/\{0\}kerberos/,"kerberos");
                       if ($0 ~ /^some:/ && some++ > 0) next;
                       if ($0 != "") print
                     }' input.txt
对于输入数据,它产生:

dn: cn=kerberos,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: kerberos
some: properties

对于我的示例输入,您的脚本工作得很好-实际数据集(在中遇到)需要稍微严格的匹配条件。谢谢你的精彩帖子,这正是我想要的:)这假设在
some:
之后,你有
junk
。我认为OP只意味着要删除其他数据。因此,这里我选择的是
awk
而不是
sed
dn: cn=kerberos,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: kerberos
some: properties