【问题标题】:How can I add some text after some sequence of text if this sequence matches certain criteria using Shell script?如果此序列与使用 Shell 脚本的某些条件匹配,我如何在某个文本序列之后添加一些文本?
【发布时间】:2018-10-24 21:44:21
【问题描述】:

我想在与 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

所以模式可能有上面提到的条件。

【问题讨论】:

  • 我没有看到拒绝投票的原因,至少应该说明为什么拒绝投票的原因,我已经根据堆栈溢出以清晰的方式提供了所有信息。
  • 不幸的是,如果您的 SQL 语句被拆分为多行,这将非常困难。如果您可以将代码格式化为每行一个语句,那么任务将更加简单。
  • @l0b0 ,是的,实际上当查询在 1 行时我尝试使用 egrep 并且你是对的,这非常容易,但不幸的是,我将直接获取我想要的原始文件应用转换。

标签: bash shell unix awk sed


【解决方案1】:

如果 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] 表达式是匹配所有字符(包括换行符)的惯用语。
  • +? 指定最短匹配。
  • $&amp; 是一个特殊变量,用于保存与最后一个模式匹配匹配的字符串。通过使用这个变量,我们可以将下面的行添加到指定的模式中。
  • 最右边斜线旁边的mg 是一个选项,告诉 Perl 我们正在处理多行文本并查找模式的多次出现。

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

希望这会有所帮助。

【讨论】:

  • 感谢您的方法,我一定会尝试检查。
【解决方案2】:

使用 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;

>

【讨论】:

    【解决方案3】:

    你必须想办法问一个简单的问题。
    我将您的要求翻译成“在每个; 之后添加一行,以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
    

    【讨论】:

    • 如果有一个以 ; 结尾的 SELECT 语句怎么办?并且不影响任何行?..
    • 是否可以将 sql%rowcount 重置为 0 ?在这种情况下,最简单的方法可能是添加像AFFECTED_ROWS := AFFECTED_ROWS + SQL%ROWCOUNT; SQL%ROWCOUNT := 0 这样的行。
    • 每条sql语句在一行时,可以用..|end|SELECT)展开异常。可以使用tr '\n' '\r' &lt; temp.sql | sed -r 's/\r\r/\n/g;s\r//g' 将它们放在一行中,但我更愿意将SQL%ROWCOUNT 设置为0。
    猜你喜欢
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多