如果此序列符合某些条件(使用Shell脚本),如何在文本序列后添加一些文本?

时间:2018-10-24 21:44:22

标签: bash shell unix awk sed

我想在符合shell脚本中提到的条件的文本之后添加一条语句。

下面是我的示例文件(SQL文件):

begin
AFFECTED_ROWS := 0;

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

DELETE FROM table_name
WHERE condition;

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);

MERGE INTO employees e
    USING hr_records h
    ON (e.id = h.emp_id)
  WHEN MATCHED THEN
    UPDATE SET e.address = h.address
  WHEN NOT MATCHED THEN
    INSERT (id, address)
    VALUES (h.emp_id, h.address);
end;

一旦我依次看到下面的任何文本,我将获取此文件并执行以下转换

1: "UPDATE ... SET ...;"
2: "DELETE ... FROM ...;"
3: "INSERT ... INTO ...;"
4: "MERGE ... INTO ... [WHEN MATCHED THEN | WHEN NOT MATCHED] ... [UPDATE|INSERT|DELETE] ... ;"

我需要在分号后添加1行:

AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

这样我的新文件将类似于以下内容:

begin
AFFECTED_ROWS := 0;

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

MERGE INTO employees e
    USING hr_records h
    ON (e.id = h.emp_id)
  WHEN MATCHED THEN
    UPDATE SET e.address = h.address
  WHEN NOT MATCHED THEN
    INSERT (id, address)
    VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

end;

我尝试在PLSQL范围内找到并实现该方法,但没有找到任何可能的方法来使行不受影响,因此我认为 文本解析,但我对awk或sed知之甚少。

现在我要尝试的是:

sed '/Patterns Go Here/a   AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;' temp.sql

因此模式可能具有上述条件。

3 个答案:

答案 0 :(得分:2)

如果您可以接受Perl,则可以轻松完成所需的操作,因为Perl擅长处理多行正则表达式。那怎么样:

perl -e '
while (<>) {
    $text .= $_;
}
$add = "\nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;";

$text =~ s/^UPDATE[\s\S]+?SET[\s\S]+?;/$&$add/mg;
$text =~ s/^DELETE[\s\S]+?FROM[\s\S]+?;/$&$add/mg;
$text =~ s/^INSERT[\s\S]+?INTO[\s\S]+?;/$&$add/mg;
$text =~ s/^MERGE[\s\S]+?INTO[\s\S]+?(WHEN MATCHED THEN|WHEN NOT MATCHED)[\s\S]+?(UPDATE|INSERT|DELETE)[\s\S]+?;/$&$add/mg;

print $text;
' inputfile

说明

  • 首先,它将所有行插入到包含换行符的变量$text中。
  • 我们将变量$add分配给其他行。
  • 然后我们开始将行添加到符合任何条件的模式。
  • Perl的s/pattern/replacement/运算符用于添加行。
  • ^字符是一个锚点,用于匹配行的开头。否则,该模式可能与WHEN条件内的关键字匹配。
  • [\s\S]表达式是一个习惯用法,用于匹配包括换行符在内的所有字符。
  • +?指定最短的匹配项。
  • $&是一个特殊变量,用于保存最后一个模式匹配所匹配的字符串。通过使用此变量,我们可以将以下行添加到指定的模式。
  • 最右斜杠旁边的
  • mg是一个告诉Perl我们正在处理多行文本并查找模式的多次出现的选项。

如果您不熟悉Perl,脚本可能看起来很模糊,但是您可以从修改代码开始,然后看看会发生什么。

希望这会有所帮助。

答案 1 :(得分:1)

使用Perl One衬纸

> export row='AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;'
> perl -ne 'BEGIN {$x=qx(cat ora_sql.txt);$x=~s/\b(UPDATE|DELETE|INSERT|MERGE)\b(.+?);/$&\n$ENV{row}/gms;print"$x"; exit }'
begin
AFFECTED_ROWS := 0;

UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

DELETE FROM table_name
WHERE condition;
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;

MERGE INTO employees e
    USING hr_records h
    ON (e.id = h.emp_id)
  WHEN MATCHED THEN
    UPDATE SET e.address = h.address
  WHEN NOT MATCHED THEN
    INSERT (id, address)
    VALUES (h.emp_id, h.address);
AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;
end;

>

答案 2 :(得分:0)

您必须寻找一种提出简单问题的方法。
我将您的要求翻译成“在每个;之后添加一行,但以AFFECTED_ROWSend开头的行除外。

解决方案将使用/^(AFFECTED_ROWS|end)/来匹配两个异常。 感叹号告诉我们,sed不应在发现异常时进行替换。

sed -r '/^(AFFECTED_ROWS|end)/ !s/;/;\nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;/' temp.sql

当您要插入带有;的值时,上述解决方案将失败。 如果要匹配的;是该行的最后一个字符,则命令为

sed -r '/^(AFFECTED_ROWS|end)/ !s/;$/;\nAFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT;/' temp.sql