1

我正在使用特定模式在 Git 中处理我的提交消息,以简化为新版本创建变更日志(https://stackoverflow.com/a/5151123/520162)。

应纳入我的变更日志的每个更改都以CHG,NEW或为前缀FIX

在生成我的变更日志时,我打印出我要为每个版本使用以下命令解析的版本:

git show --quiet --date=short --pretty=format:"%cd %an %s%n%n%w(100,21,21)%b%n" $CURRENTREVISION

主题 ( %s) 包含修改的主题。

接下来,我使用 SED 修改生成的输出,以使其符合我的变更日志文件的需要。

现在,碰巧在主题行中,多次出现CHG,NEWFIX。我的主题输出如下所示:

DATE NAME FIX first change NEW second change CHG third change

我想在我的关键字的第一次出现之前添加一个换行符,以便每个CHG,NEWFIX开始一个新行:

DATE NAME FIX first change
          NEW second change
          CHG third change

为了实现这一目标,我必须告诉 SED 什么?

4

4 回答 4

2

sed不是最合适的工具

有了awk它看起来像这样。

awk '{n=0; for (i=1; i<=NF; i++) {if ($i ~ /(NEW|FIX|CHG)/) {$i=(n++?"\n          ":"")$i}}}7'
  • n=0(重新)设置标志
  • for (i=1; i<=NF; i++)循环遍历该行的每个字段
  • if ($i ~ /(NEW|FIX|CHG)/)如果该字段是标记之一
    • $i=(n++?"\n ":"")$i通过添加适当的前导空格(或无)来更新字段
  • 7真值模式打印出当前行。
于 2014-12-08T14:44:04.697 回答
2
awk '{while(++i<=NF){if($i~/FIX|NEW|CHG/){if(f){$i="\n"$i}else{f=1}}}}1'

甚至更小:

awk '{while(++i<=NF){if($i~/FIX|NEW|CHG/){if(f++){$i="\n"$i}}}}1'

例子:

$echo "DATE CH NAME FIX first change NEW second change CHG third change" | awk '{while(++i<=NF){if($i~/FIX|NEW|CHG/){if(f){$i="\n"$i}else{f=1}}}}1'

DATE CH NAME FIX first change 
NEW second change 
CHG third change

1st to last田野走。对于匹配这 3 个模式中的任何一个的字段,我们检查 if ,如果f=1第一次匹配,这将是错误的。因为我们这样做了f++,所以对于下一场比赛,它将是真实的,因此"\n"将在之前添加。

于 2014-12-08T14:46:10.030 回答
1
sed '/^DATE NAME/ {
:cycle
   s/\(.\{1,\}\) \(FIX .*\)/\1\
\2/g
   t cycle
   s/\(.\{1,\}\) \(NEW .*\)/\1\
\2/g
   t cycle
   s/\(.\{1,\}\) \(CHG .*\)/\1\
\2/g
   t cycle

   s/\n/&          /g
   s/\n */ /
   }' YourFile

类似于 posix 版本的东西(--posix在 GNU sed 上)。

一个简单的

   s/\(.\{1,\}\) \(\(CHG|FIX|NEW\) .*\)/\1\
\2/g
   t cycle

s///可以先用 GNU sed替换 3以允许|

我用第一个/^DATA NAME/作为过滤器确保了一点,但如果只处理这种线,就不需要这个(和相关的{ }

于 2014-12-08T14:58:39.767 回答
0

sed听起来不像是适合这项工作的工具。中保存的状态sed非常有限,你的目标需要一个计数器,这在sed. 我认为您以后不会乐意维护您的代码。

相反,我认为也许Perl是一个很棒的工具。

像这样的东西:

while(<STDIN>){
    my @matches = m/^(.*?)((?:FIX|NEW|CHG).*?)*$/;
    my $date_name = unshift @matches; # only FIX, NEW, CHG remains now
    print $date_name, unshift @matches;
    while (@matches) { print "\t\t", unshift @matches; }
}

管道输入您的原始数据,并重定向到 shell 中的文件。

于 2014-12-08T14:35:42.160 回答