【问题标题】:unix extract data from fileunix 从文件中提取数据
【发布时间】:2018-09-27 20:18:14
【问题描述】:

我有一个来自 informix 数据库导出的 file.sql 文件。 以下是文件的一小部分(我稍微更改了数据以使其匿名):

grant dba to "xxx";
grant dba to "yyy";
grant dba to "zzz";

{ TABLE "xxx".table1 row size = 66 number of columns = 5 index size = 54 }
{ unload file name = table00100.unl number of rows = 307 }

create table "xxx".table1 
  (
    field1 char(2) not null ,
    field2 char(10) not null ,
    field3 char(30),
    field4 char(20) not null ,
    field5 date not null 
  );
revoke all on "xxx".table1 from "yyy";

我需要从这个文件中将 table00100.unl 文件重新命名为原始表名。所以我需要这样的输出:

mv table00100.unl table1

我已经设法在两个文件之间使用了一点 awk 和 sed,但是如果没有中间的临时文件,这不是更简单吗?我的代码示例:

awk '{for(i=1;i<=NF;i++) {if ($i=="unload") {print $(i+4)} else {if ($i=="TABLE") print $(i+1)}}}' file.sql | sed 's/".*".//' > temp.out
awk 'NR%2{printf "%s ",$0;next;}1' temp.out | awk '{for (i=NF;i>0;i--) if (i > 1) printf("mv %s ",$i); else printf("%s\n",$i)}' > temp.shl

【问题讨论】:

    标签: unix awk sed


    【解决方案1】:

    如果你想单独使用 awk:

    /TABLE/ {
        sub("\".+\"\\.", "", $3);
        table = $3;
    }
    /unload/ {
        print "mv", $6, table;
    };
    

    【讨论】:

    • 我可以更改打印“mv”,$6,表吗?到系统(“mv”$6“”表);立即执行移动?
    • 当然可以,但恕我直言,您最好先将这些脚本输出到控制台或文件以检查其正确性。
    • sub() 的第一个参数是正则表达式而不是字符串,因此请使用正则表达式分隔符,这样 awk 就不必解析它两次,即 sub(/".+"\./, "", $3)。此外,该移动应提供引号printf "mv \047%s\047 \047%s\047\n", $6, table,因此当shell 稍后执行它时,它不会暴露于通配符、分词和文件名扩展。最后 - 你不需要每行尾随分号。
    • @nightfox79 你真的不应该让 awk 参与打印mv 或执行mv,因为这会在 awk 脚本和调用 shell 脚本之间创建紧密耦合。只需让 awk 查找并打印 from 和 to 名称,然后让调用 shell shell 执行 mv 或其他任何操作。
    【解决方案2】:

    类似于 georgexsh 的解决方案,但使用 gensub:

    awk '/TABLE/{table=gensub(/.*\./, "", "", $3)}/unload/{print "mv", $6, table }'
    

    【讨论】:

      【解决方案3】:
      awk '($0 ~ /{ *TABLE/)  { match($0,/TABLE */); to=substr($0,RSTART+RLENGTH);
                                match(to," ");       to=substr(to,1,RSTART-1);
                                match(to,"[.]");     to=substr(to,RSTART+1);
                              }
           ($0 ~ /{ *unload/) { match($0,"name *= *"); from=substr($0,RSTART+RLENGTH); 
                                match(from," ");       from=substr(from,1,RSTART-1)
                              }
           (from!="") && (to!="") { exit }
           END {print "mv "from" "to}' file
      

      我让它如此“复杂”的原因是我不确定您输入中的所有间距是否一致,以及大括号中的顺序是否始终相同。

      【讨论】:

      • 这只给出了第一个表,我有 300 多行这样的行,我该如何循环这个
      【解决方案4】:

      使用 perl 一行(当然它很长:-))

      > cat informix_unload.txt
      grant dba to "xxx";
      grant dba to "yyy";
      grant dba to "zzz";
      
      { TABLE "xxx".table1 row size = 66 number of columns = 5 index size = 54 }
      { unload file name = table00100.unl number of rows = 307 }
      
      create table "xxx".table1
        (
          field1 char(2) not null ,
          field2 char(10) not null ,
          field3 char(30),
          field4 char(20) not null ,
          field5 date not null
        );
      revoke all on "xxx".table1 from "yyy";
      
      grant dba to "xxx";
      grant dba to "yyy";
      grant dba to "zzz";
      
      { TABLE "xxx".table2 row size = 66 number of columns = 5 index size = 54 }
      { unload file name = table00200.unl number of rows = 307 }
      
      create table "xxx".table2
        (
          field1 char(2) not null ,
          field2 char(10) not null ,
          field3 char(30),
          field4 char(20) not null ,
          field5 date not null
        );
      revoke all on "xxx".table1 from "yyy";
      -- other data
      
      > perl -ne 'BEGIN{$x=qx(cat informix_unload.txt);while($x=~m/(.+?)unload file name = (\S+)(.+?)create table (\S+)(.+)/osm){$x=$5;print "$2 $4\n";}exit}'
      table00100.unl "xxx".table1
      table00200.unl "xxx".table2
      >
      

      看看这个

      【讨论】:

        猜你喜欢
        • 2012-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-01
        • 2023-03-25
        • 2013-07-16
        • 2020-12-20
        相关资源
        最近更新 更多