【问题标题】:Finding a pattern and extracting it into another file using sed in BASH在 BASH 中使用 sed 查找模式并将其提取到另一个文件中
【发布时间】:2009-10-06 10:09:39
【问题描述】:

我有一些包含表创建 SQL 的 SQL 脚本 陈述。我想删除所有具有 外键映射。

例如下面是一个脚本。

CREATE TABLE x (
    ORG_ID  NUMBER primary key,
    BILLING_doc xmltype
);

alter table x
 add (constraint fk_x foreign key
  (org_id) references organization\r
  (org_id))
/

我想删除引用 外键语句并将其放在另一个文件中。正如你看到的 语句以 / 结尾。有些文件以分号结尾。

我想使用sed 执行此操作。请注意,alter 语句 此处显示的是跨行分布,而不是单个 行。

感谢任何帮助。

在工作时,我发现了以下内容,但它不适用于所有脚本:

sed -e '/./{H;$!d;}' -e 'x;/foreign/!d;' myfile.sql

上述命令不起作用的脚本:

create table io_template
(
    io_template_id number,
    io_template_name varchar2(50),
    acl_id number,
    org_id number,
    is_active varchar2(1),
    xsl_template varchar2(50),
    email_body varchar2(2000),
    purpose varchar2(50) default 'CUSTOMER' not null,
    content_type varchar2(50) default 'PDF' not null
);

alter table _io_template add constraint io_template_pk
      primary key (io_template_id);

alter table _o_template add constraint io_template_acl_fk
      foreign key (acl_id) references scum_acl(acl_id);

alter table io_template add constraint io_template_org_fk
      foreign key (org_id) references scum_organization(org_id);

alter table io_template add constraint io_template_name_uk
      unique (org_id, _io_template_name);

【问题讨论】:

  • 查看我编辑的答案以获取 sed 脚本以进行提取。

标签: bash shell sed


【解决方案1】:

您没有确切说明 sed 脚本如何在第二个 SQL 脚本上不起作用,但我假设它会打印所有行。

当我针对两个 SQL 脚本运行它时,它似乎工作正常。仅输出带有foreign keys 的alter table 语句。

对我来说可能出错的第一个线索是两个 SQL 脚本的格式不同。有大写、不同的布局、斜线与分号,以及可能的杂散“\r”。

所以我在第二个 SQL 脚本上运行 unix2dos 并再次运行 sed 脚本。这次它输出所有行。

所以,要解决您的问题,请尝试执行相反的操作:

dos2unix sqlscriptname

编辑:

要修改原始 SQL 文件并将带有 foreign keys 的 alter table 语句保存到名为 foreign.out 的文件中,您可以这样做:

 sed -i.bak  -e '/./{H;$!d;}' -e 'x;/foreign/w foreign.out' -e '/foreign/d' sqlscriptname

这将保留原始 SQL 脚本,但删除了语句,将未更改的脚本备份到 sqlscriptname.bak 并将语句写入 foreign.out。

【讨论】:

  • @丹尼斯威廉姆森。对于第二个脚本,这是问题所在。使用 dos2unix 转换文件,然后它工作正常。
  • @Dennis Willimson。该命令有效。 +1 用于提供改进的解决方案。谢谢。
【解决方案2】:

未经测试:

perl -e '$/=""; while(<>) { print if / references /; }' all.sql > references.sql

停止使用 sed。

【讨论】:

  • @reinierpost。试过这个。得到与 SED 相同的结果。但是,如果您复制我粘贴的第二个 sql 代码,则无法使用。知道为什么吗?
  • @reinierpost。如何从现有文件中删除提取的行? +1。
  • @Viky:它对我有用。要获取所有不匹配的内容,请添加 !在 if 之后,或者如果您愿意,可以将 if 更改为“除非”。要将输入文件替换为结果输出,请在 -e 之前添加 -i.bak,原始文件将在 all.sql.bak 中结束。
  • @reinierpost。希望从原始文件中删除模式而不更改其名称,并在文件中更新删除的模式。
  • 按照我的建议去做。首先没有!并且没有 -i.bak,然后两者都有。然后删除的行将在 eferences.sql 中。如果您需要更频繁地执行此类操作,建议您参加一些课程或由经验丰富的脚本编写者提供辅导。
【解决方案3】:

下面的脚本对我有用

#!/bin/bash
for filename in `ls *.sql`
do
dos2unix $filename
sed -e '/./{H;$!d;}' -e 'x;/[fF][oO][rR][eE][iI][gG][nN]/!d;' $filename >> fk_file.sql
sed -e '/./{H;$!d;}' -e 'x;/[fF][oO][rR][eE][iI][gG][nN]/d' $filename > $filename.new
mv $filename.new $filename
done

【讨论】:

  • 你可以做for filename in *.sql 不需要ls。
  • 查看我编辑的答案以在没有mv 的情况下在一行中执行您的sed/sed/mv。
【解决方案4】:

我最初的想法是分两步完成:

1。使用 grep 将模式拉出并将其放在单独的文件中

2。使用 sed 从原始文件中删除它

但可能有更好的方法。

grep -i "alter.*foreign key.*[\/|;]" filename.txt > alter_statements.txt

sed  -e "/alter.*foreign key.*[\/|;]/d" filename.txt > everything_else.txt

不过,这只适用于单行的 alter 语句。

[编辑以更正格式]

【讨论】:

    猜你喜欢
    • 2017-01-24
    • 1970-01-01
    • 2010-10-16
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 2013-02-09
    • 2021-07-27
    相关资源
    最近更新 更多