找到以以下内容开头的第一行下列的

找到以以下内容开头的第一行下列的

让我们提出我的问题以便更好地解释。我使用的是 cygwin,安装基于以下格式的 setup.ini:

    @ package-name
    sdesc: "short description, on one line"
    ldesc: "long description of arbitrary length, commonly multiple lines"
    category: categories in which the packege belonges, one line
    requires: packages (libs etc) required by this package, one line

然后是下面的包,等等。

我需要的是,给定一个包名称,输出该包所需的所有包(如果可能,不带“requires”前缀)。

我确信这是基本的 grep,但我是新手。谢谢。

答案1

我不确定你将如何使用 grep 来完成此任务,但对于此类任务我更喜欢 awk。它可以更好地控制我想做的事情。虽然我不是 awk 方面的专家并且仍在学习,但这就是我如何实现这一点的。

PKGNAM="package-name"; awk "/$PKGNAM\$/,/requires:/ { if ( \$0 ~ /requires:/ ) { sub( /^requires:.?/, \"\"  ); print } }"

更新:更新了示例 awk 命令,现在它使用 PKGNAM 变量来匹配 pacakge 名称。

在此输入图像描述

HTH。

答案2

Grep 独立处理所有行,因此它无法单独完成这项工作。

awk 是一个通用的文本处理工具。跟踪当前包是什么(在变量 中),如果在正确的包中找到一行,p则输出匹配项(删除前缀)。requires:requires:

<setup.ini awk -vpackage='NAME_OF_PACKAGE' '
    sub(/^@ */,"") {p=$0}
    p==package && sub(/^requires: */,"") {print}
'

另一种 awk 方法是处理由换行符@序列而不是换行符分隔的输入。或者,由于包部分之间有一个空行,因此按段落处理输入:传递一个空字符串作为记录分隔符RS(这意味着记录由一个或多个空行分隔)。然后,对于所需记录中的每一行,如果该行以 开头requires:,则打印它(减去前缀)。

<setup.ini awk -vpackage='NAME_OF_PACKAGE' -vRS= -vFS='\n' '
    sub(/^@ */,"") && $1==package {
        for (i=2; i<NF; i++) {if (sub(/^requires: */,"",$i)) print $i}
    }'

另一种可能性是 Perl 的段落模式 ( -00)。如果段落以右标题开头(/REGEXP/m表示多行匹配,因此$锚点表示行尾而不是字符串尾),并且它包含一行requires:,则打印该行(减去前缀)。

<setup.ini package=NAME_OF_PACKAGE perl -00 -ne '
    /\A@ *$ENV{package}$/m and /^requires: *(.*)$/m and print "$1\n"'

这是为 (GNU) sed 爱好者准备的。 (你不应该理解这一点。)

sed -ne '/^@/ { h; b; }; G; s/^requires: *\(.*\)\n@ *NAME_OF_PACKAGE$/\1/p'

答案3

这是一个sed无需反向引用即可完成此操作的解决方案。

# cf. "3.3. Addressing and address ranges",
# http://sed.sourceforge.net/sedfaq3.html#s3.3 (esp. (6) Relentless. ...)

PKGNAME="package-name"
sed -ne '/^ *@ *'"${PKGNAME}"'/{
:a
N
/\n *requires: /!ba
s/.*\n *requires: *//
p
}' setup.ini 

如果命令放在单独的行上(或者至少后面有一个换行符),Gilles(GNU)的sed解决方案可以在 Mac OS X 10.6.7(使用 FreeBSD sed)上运行。b

PKGNAME="package-name"
sed -ne '/^ *@ *'"${PKGNAME}"'/{h
b
};G;s/^ *requires: *\(.*\)\n *@ *'"${PKGNAME}"' *$/\1/p' setup.ini

相关内容