1

我正在尝试制作一个简单的 bashscript,给定 git diff 的 sql 模式定义文件的输出,将能够创建更新脚本和撤消脚本。所以有这样的输入:

 create table xxx
 (
-       aaa numeric(18) primary key,
-       bbb numeric(18) not null,
-       ccc numeric(18) not null,
+       aaa INT UNSIGNED AUTO_INCREMENT primary key,
+       AlarmId INT UNSIGNED not null,
+       ccc INT UNSIGNED not null,
        ddd smallint not null,
        eee varchar(2),
        fff varchar(2),
    )

假设我想制作一个更新脚本。我将所有create语句更改为alter's,然后删除所有不必要的行,最后用change语句替换'+'标记(它;s mysql脚本)。我喜欢这样:

sed "s/^\s*create/ALTER/g" < $infile | sed "/^\s\|@/d" | sed "/^-/d" | sed "s/^+\s*\(\`\?\w\+\`\?\)/\tCHANGE \1 \1/g"

所以我终于得到了这样的东西:

ALTER table xxx
        CHANGE aaa aaa INT UNSIGNED AUTO_INCREMENT primary key,
        CHANGE bbb bbb INT UNSIGNED not null,
        CHANGE ccc ccc INT UNSIGNED not null,
        CHANGE ddd ddd smallint not null,
ALTER table yyy
        CHANGE aaa aaa INT UNSIGNED primary key,
        CHANGE bbb bbb smallint not null,
        CHANGE ccc ccc smallint not null,
        CHANGE ddd ddd INT UNSIGNED not null,
        CHANGE eee eee varchar(1024) not null
ALTER table zzz
(and so on)

我需要做的最后一件事是用冒号完成每个语句 - 我完全被困在那里。基本上,我需要找到每个ALTER语句(或 EOF),并在其上方的行尾添加一个冒号(可能替换现有的逗号)。我可以使用它的s命令在 vim 中做到这一点:

%s/\(,\)\=\_s\+\(ALTER.*\|\%$\)/;\r\2

但我未能将其转换为 sed 语法。看来,强迫 sed 接受多行模式是一项艰巨的工作。所以 - 谁能告诉我该怎么做?我猜 sed 不是唯一的选择。这只是我的第一选择(不是最好的:))也许有一些开箱即用的解决方案,而我只是在重新发明轮子?

4

2 回答 2

2

有趣的方法(也很脆弱 - 想象一下将几列放在同一行上的变化)。Perl 可以帮助您使用分号:

 perl -0777 -pe 's/[,\s]+ALTER/;\nALTER/g;
                 s/$/;/' < input > output
  • -0777“啜饮”整个文件(而不是逐行读取)
  • -p打印处理后读取的内容
  • [,\s]+匹配空格和逗号,必须至少有一个这样的字符(它防止在第一个 ALTER 之前插入分号)。
  • 第二个替换添加了最后的分号。
于 2015-10-22T08:14:19.517 回答
0
sed -n '
   /^[[:blank:]]*create/ {
      s//ALTER/
      H
      b
      }

   /^+\([[:blank:]]*\)\([^[:blank:]]\{1,\}\)/ {
      s//\1CHANGE \2 \2/
      H
      }
   $ !b

   x
   s/,\(\nALTER\)/;\1/g
   s/.\(.*\),$/\1;/p
   ' YourFile

您需要使用保持缓冲区来一起处理所有(几条)行(操作xH此处)

于 2015-10-22T09:59:39.133 回答