【问题标题】:awk '/range start/,/range end/' within scriptawk '/range start/,/range end/' 在脚本中
【发布时间】:2011-11-29 20:54:46
【问题描述】:

如何在独立的 awk 脚本中使用 awk 范围模式 '/begin regex/,/end regex/'

为了澄清,给定程序 csv.awk:

#!/usr/bin/awk -f

BEGIN {
FS = "\"" 
}

/TREE/,/^$/
{
  line="";
        for (i=1; i<=NF; i++) {
                if (i != 2) line=line $i;
        }

        split(line, v, ",");
        if (v[5] ~ "FOAM") {
                print NR, v[5];
        }
}

和文件块:

TREE
10362900,A,INSTL - SEAL,Revise
,10362901,A,ASSY / DETAIL - PANEL,Revise
,,-203,ASSY - PANEL,Qty -,Add
,,,-309,PANEL,Qty 1,Add
,,,,"FABRICATE FROM TEKLAM NE1G1-02-250 PER TPS-CN-500, TYPE A"
,,,-311,PANEL,Qty 1,Add
,,,,"FABRICATE FROM TEKLAM NE1G1-02-750 PER TPS-CN-500, TYPE A"
,,,-313,FOAM SEAL,1.00 X 20.21 X .50 THK,Qty 1,Add
,,,,"BMS1-68, GRADE B, FORM II, COLOR BAC706 (BLACK)"
,,,-315,FOAM SEAL,1.50 X 8.00 X .25 THK,Qty 1,Add
,,,,"BMS1-68, GRADE B, FORM II, COLOR BAC706 (BLACK)"
,PN HERE,Dual Lock,Add
,
10442900,IR,INSTL - SEAL,Update (not released)
,10362901,A,ASSY / DETAIL - PANEL,Revise
,PN HERE,Dual Lock,Add

我想要这个输出:

27 FOAM SEAL
29 FOAM SEAL

将命令行形式'/begin regex/,/end regex/' 添加到脚本以仅对这些行进行操作的语法是什么?我所有的尝试都会导致语法错误,而谷歌搜索只会给我 cli 表单。

【问题讨论】:

    标签: awk


    【解决方案1】:

    为什么不使用2个步骤:

    % awk '/start/,/end/' < input.csv | awk csv.awk
    

    【讨论】:

      【解决方案2】:

      简单地做:

      #!/usr/bin/awk -f
      
      BEGIN {
      FS = "\"" 
      }
      
      /from/,/to/ {
        line="";
              for (i=1; i<=NF; i++) {
                      if (i != 2) line=line $i;
              }
      
              split(line, v, ",");
              if (v[5] ~ "FOAM") {
                      print NR, v[5];
              }
      }
      

      如果from to 正则表达式是动态的:

      #!/usr/bin/awk -f
      
      BEGIN {
          FS = "\"" 
          FROM=ARGV[1]
          TO=ARGV[2]
          if (ARGC == 4) { # the pattern was the only thing, so force read from standard input                   
             ARGV[1] = "-"
          } else {
             ARGV[1] = ARGV[3] 
          }
      }
      
      { if ($0 ~ FROM) { p = 1 ; l = 0} }
      { if ($0 ~ TO)   { p = 0 ; l = 1} } 
      
      {  
        if (p == 1 || l == 1) {
         line="";
              for (i=1; i<=NF; i++) {
                      if (i != 2) line=line $i;
              }
      
              split(line, v, ",");
              if (v[5] ~ "FOAM") {
                      print NR, v[5];
              }
         l = 0 } 
      }
      

      现在您必须将其命名为:./scriptname.awk "FROM_REGEX" "TO_REGEX" INPUTFILE。最后一个参数是可选的,如果缺少STDIN可以使用。

      HTH

      【讨论】:

      • 现在让“from”和“to”动态化,OP 想要从命令行输入。
      • 很抱歉,这是在哪里提到的?无论如何,编辑解决方案。
      • 仅仅为了改变'from'和'to'范围而改变脚本会很可惜,不是吗? :)
      • 在您的第一个示例中(更接近我的要求),在该位置添加正则表达式会将未过滤的输出从 /from/ 打印到出现的第一行 v[5],然后打印 NR, v [5]。我只想打印 NR, v[5]。
      • @ZsoltBotykai: /me 看着我更简单的一个班轮。在问题上增加复杂性并不总是最明智的做法。
      【解决方案3】:

      您需要向我们展示您的尝试。有什么关于 /begin regex/ 或 /end regex/ 你没有告诉我们,否则你的脚本应该可以工作,即

      #!/usr/bin/awk -f
      
      BEGIN {
      FS = "\"" 
      }
      
      /begin regex/,/end regex/{
        line="";
              for (i=1; i<=NF; i++) {
                      if (i != 2) line=line $i;
              }
      
              split(line, v, ",");
              if (v[5] ~ "FOAM") {
                      print NR, v[5];
              }
      }
      

      或者你使用的是旧的 Unix,旧的 awk 是 /usr/bin/awk,新的 awk 是 /usr/bin/nawk。还要看看你是否有 /usr/xpg4/bin/awk 或 gawk(路径可以是任何东西)。

      最后,向我们展示您收到的错误消息。

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2014-02-10
        • 1970-01-01
        • 2013-01-23
        • 1970-01-01
        • 1970-01-01
        • 2015-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多