awk 重复行太多次

awk 重复行太多次

我正在使用 awk 创建一个包含文本行并使用数字输入文件的文件。我想替换每个数字一次,即第 1 行获取第一个数字,第 2 行获取第二个数字,第 3 行获取第三个数字。但是,每行都分配了第一个数字,然后每行都分配了第二个数字,依此类推...

这是我的文本输入文件(test.awk):

{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}

这是数字的输入文件:

-0.00432739
0.41369093
0.00000000

命令:awk -f test.awk < input.txt > new.txt

生成以下代码,其中三行重复三次:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

我想要的是这个:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

谁能告诉我如何阻止它将每个数字分配给每一行然后重复这 3 行?

答案1

使用模 3 ( %) 并进行少许修正printf(\"%%f %%s\n\",$1=="$1",$2)

{
  if (NR%3==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==0) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

如果你的文件中有多于三行代码,那么取模也是一个好主意。上面代码中的input.txt数字取决于文件中的行数。如果文件中有四行代码,那么你需要类似下面的代码:3printftest.awkprintf

{
  if (NR%4==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==3) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")};
  if (NR%4==0) {printf("\n($2 == \"foo.bar\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

输出三条线input.txt

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

输出三行以上input.txt

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

答案2

您可以使用以下 awk 代码(test.awk):

BEGIN{count=0}{count++}{if(count==1){printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1; h=0;}"); }}

答案3

我只需将数字保存在数组中并使用它即可。首先,修改您的数组,test.awk使其看起来像这样:

($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

您可以用以下命令自动执行此操作:

sed -i 's/^{//;s/}$//;s/printf("\\n//;s/");//' test.awk 

完成后,您可以使用此脚本获取输出:

$ awk 'NR==FNR{a[NR]=$1; next}{gsub(/"\$1"/,a[FNR]); print}' input.txt test.awk 
($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;} 

解释

NR是当前行号,FNR当前文件。因此,只有在读取第一个文件时,两者才相等。因此,awk上面脚本的第一部分(NR==FNR{a[NR]=$1; next})创建一个数组,其键是文件的行号input.txt,其值是相应的数字。然后它运行next以移动到下一行,而不执行脚本的第二部分。

第二部分将用数组中存储的第二个文件当前行号的"$1"值替换字符串( )。结果就是您所要求的。aFNR


另一种方法是使用一些技巧。不要使用脚本,而是使用paste来连接文件并awk进行替换。首先test.awk按上述方法进行修改,然后:

$ paste input.txt test.awk | awk '{gsub(/"\$1"/,$1);$1="";print;}'
 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;}
 ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;}
 ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;}

解释

paste命令将同时打印输入文件的每一行。因此,使用上面的输入,它将打印:

$ paste input.txt test.awk
-0.00432739 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.41369093  ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.00000000  ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

然后将其通过 awk 脚本传递,该脚本

  • 用于gsub将所有出现的 替换为( )"$1"的值;$1gsub(/"\$1"/,$1);
  • 完成后,$1将其设置为空($1=""),以便第一个文件的数字不会打印在行首。
  • 最后,它打印结果行(print)。

答案4

Janet,你需要让 awk 知道,在将第一行代码应用到第一个输入行后,它应该跳转到下一个输入行。然后,在应用第二行代码后,它应该跳转到下一个输入行,依此类推。否则,awk 会在每个输入行上应用每一行代码。最简单的方法是在每一行代码后插入一个 getline 命令(除了最后一行之后,因为它没用):

[alessandro@localhost ~]$ cat /tmp/a.awk
{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}
[alessandro@localhost ~]$ cat /tmp/a.txt
-0.00432739
0.41369093
0.00000000
[alessandro@localhost ~]$ awk -f /tmp/a.awk /tmp/a.txt
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}[alessandro@localhost ~]$ 

相关内容