我有一个Makefile
,它有变量version
和build
(这些不是唯一的变量,可以按不同的顺序定义)。仅使用sed,我想将这些值组合成一个版本字符串。
到目前为止,我已经:
sed -n -e '/=/{s/version.*=\(.*\)/\1\./p;s/build.*=\(\d*\)*/\1/p}' Makefile
但两个值都用换行符分隔。以上产生以下输出:
0.8.2. 1
我想:
0.8.2.1
我尝试了N
,但无法确定如何在此引用中使用它。
为什么'仅限'限制?我想学习它,这对我来说是最好的方式。
独立样本:
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
答案 0 :(得分:4)
以下是基于相同的想法:存储版本和内部版本号,然后在输入结束时打印它们。
当涉及到存储时,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; }'
这会在字符串的末尾产生换行符,但希望这不会成为问题。
awk系列实用程序支持变量,使任务更加简单。它们具有特殊变量OFS,输出字段分隔符和ORS,即输出记录分隔符。 awk的print
在每个参数之间输出OFS,在最后输出ORS。特殊模式END
在输入结束后匹配。
awk -v OFS=. -v ORS='' \
'/^version.*=/ {sub(/^[^=]*=/, ""); version=$0;} \
/^build.*=/ {sub(/^[^=]*=/, ""); build=$0;} \
END {print version, build;}'
如果您不关心尾随点,并且可以确定makefile中版本和构建行的顺序:
awk -v ORS=. '/(version|build).*=/ { sub(/^[^=]*=/, ""); print; } '
语言表达能力的持续向上是perl。 perl的END
具有与awk类似的功能,标记要在进程结束时运行的块。哈希可用于存储完整版本号的部分,允许行匹配并存储版本和构建以组合成一行。
perl -n -e '$ver{$1} = $2 if /^(version|build)[^=]*=(.*)/; \
END {$,="."; print @ver{"version","build"}};'
虽然使用sed是一项有趣的练习,但练习中的价值在于通过练习来强化自己。如果您必须转向其他人,最好不要专注于您尝试solve the problem的方式,而是找出推荐的方法。你会了解更多。
答案 1 :(得分:1)
尝试使用makefile:
sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' makefile
使用示例文本进行测试:
kent$ sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' <<<"foo=1
dquote> version=0.8.2
dquote> bar=2
dquote> build=1
dquote> bam=bug-AWWK
dquote> EOF"
0.8.2.1
如果版本显示在版本之前:
kent$ sed -rn -e '/^(version|build)/{s#^.*=##;H;}' -e'${x;s#\n##;s#\n#\.#;p}' <<<"foo=1
bar=2
build=1
bam=bug-AWWK
version=100.8.2"
1.100.8.2
答案 2 :(得分:0)
这可能对您有用:
cat makefile |
sed '/^\(version\|build\)/H;${x;s/^\(\nbuild.*\)\(\n.*\)/\2\1/;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d'
0.8.2.1
tac makefile |
sed '/^\(version\|build\)/H;${x;s/^\(\nbuild.*\)\(\n.*\)/\2\1/;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d'
0.8.2.1
如果版本在构建之前或之后没有打扰,那么:
sed '/^\(version\|build\)/H;${x;s/^.*=\(.*\)\n.*=\(.*\)/\1.\2/p};d'
0.8.2.1
阅读@outis解决方案后,这是他的平面浏览解决方案的改进版本:
sed '/^version=/{s///;G;h};/^build=/{s//./;H};${g;s/\n//gp};d' makefile
答案 3 :(得分:0)
如果您对awk
开放,那么这是另一种解决方案。防止因输入sed
代码而导致的手指痉挛。 No offence to the brilliant solutions offered by potong and kent
;)
awk -F"=" '
BEGIN{i=1}
(/version|build/){a[i]=$NF;i++}
END{for(i=1;i<=2;i++) if(i==1) {printf a[i]"."} else printf a[i]}' Makefile