使用 sed 在 1 行中打印多个匹配项

Łuk*_*ner 2 sed

我有一个Makefile, ,它有变量versionbuild(这些不是唯一的变量,可以按不同的顺序定义)。仅使用 sed,我想将这些值组合成一个版本字符串。

到目前为止我已经得到:

sed -n -e '/=/{s/version.*=\(.*\)/\1\./p;s/build.*=\(\d*\)*/\1/p}' Makefile
Run Code Online (Sandbox Code Playgroud)

但两个值均由换行符分隔。以上产生以下输出:

0.8.2。
1

我想要:

0.8.2.1

我尝试过N,但不知道如何在这个网站上使用它。

为什么“仅限 sed”限制?我想学习它,这对我来说是最好的方法。

独立样本:

sed -n -e '/=/ {s/version.*=\(.*\)/\1\./p;s/build.*=\(\d*\)*/\1/p}' <<EOF
foo=1
version=0.8.2
bar=2
build=1
bam=bug-AWWK
EOF
Run Code Online (Sandbox Code Playgroud)

out*_*tis 5

以下内容都基于相同的想法:存储版本号和内部版本号,然后在输入末尾打印它们。

在存储方面,sed 具有模式空间(从当前行的值开始)和保持空间(可用于在进程持续时间内保存值)。版本应该被添加到保持空间中的值之前,这可以通过使用 . 将保持空间附加到模式空间来完成G。构建应附加到保留空间,这可以使用 来完成H。要删除创建的换行符H,保留空间将移回模式空间。G在这两种情况下,由和创建的换行符H都会被 删除s///,然后用 回到保留空间h。输入的结束由$地址表示,在该地址处,保留空间移回模式空间并打印。看到的时间比较短:

sed -n -e '/^version.*=/ {s/[^=]*=//; G; s/\n//; h; } ' \
       -e '/^build.*=/ { s/[^=]*=//; H; g; s/\n/./; h; } ' \
       -e '$ { g; P; }'
Run Code Online (Sandbox Code Playgroud)

这会在字符串末尾产生一个换行符,但希望这不会成为问题。

awk 系列实用程序支持变量,使任务更加简单。它们具有特殊变量 OFS(输出字段分隔符)和 ORS(输出记录分隔符)。awkprint输出每个参数之间的 OFS,以及最后的 ORS。特殊模式END在输入结束后匹配。

awk -v OFS=. -v ORS='' \
    '/^version.*=/ {sub(/^[^=]*=/, "");  version=$0;} \
     /^build.*=/ {sub(/^[^=]*=/, ""); build=$0;} \
     END {print version, build;}'
Run Code Online (Sandbox Code Playgroud)

如果您不关心尾随点并且可以确定 makefile 中版本和构建行的顺序:

awk -v ORS=. '/(version|build).*=/ { sub(/^[^=]*=/, ""); print; } '
Run Code Online (Sandbox Code Playgroud)

语言的表达能力继续向上的是perl。perlEND具有与 awk 类似的功能,标记要在进程结束时运行的块。哈希可用于存储完整版本号的各个部分,允许行匹配并存储版本和构建以组合成一行。

perl -n -e '$ver{$1} = $2 if /^(version|build)[^=]*=(.*)/; \
            END {$,="."; print @ver{"version","build"}};'
Run Code Online (Sandbox Code Playgroud)

虽然使用 sed 可以进行有趣的练习,但练习的价值在于通过练习来增强自己。如果您必须求助于其他人,最好不要关注您如何解决问题,而是寻找推荐的方法。你会学到更多。