使用system()在Awk中只运行一次外壳命令,即只打印一次文本(&q;) [英] Run Shell Command Inside Awk only Once 'per command' Using System(), i e, print only Once "text"

查看:15
本文介绍了使用system()在Awk中只运行一次外壳命令,即只打印一次文本(&q;)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据此问题的先前答案,我有以下awk脚本的示例https://stackoverflow.com/a/69874658/10824251

awk 
'
FNR==1 {++f}

f==1 {a[i++]=$0}
f==2 {if ($0~/home_cool/) {gsub(/home_cool/, a[int(j++/2)%2]) }; print > "2.txt"}
k==1 {system("echo 'text' && sleep 4")}
f==3 {if ($0~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}
k==1 {system("echo 'text2' && sleep 4")}
f==4 {if ($0~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "4.txt"}' 
    1.txt 0.txt 0-1.txt 0-2.txt

我尝试仅在创建2.txt文件之后和创建3.txt文件之前添加一次运行的命令外壳程序。

这意味着只有在完全创建2.txt文件后才能执行特定的外壳命令。

解决方案还应能够在4.txt要创建之前打印text2

我正在使用system(),到目前为止,我的尝试不能很好地工作,唯一不能工作的是外壳脚本执行了3次,而不是1次(从屏幕上的3个text打印可以看出这一点)。

在创建2.txt之前,echo 'text'只运行了一次,我可以做些什么来查看真正遗漏了什么才能解决此问题?

我尝试在system()(system("counter=0; if [[ "$counter" -gt 2 ]] then echo "text" fi; sleep 4"))中插入一个计数器(没有while),但没有作用,而且这真的没有多大意义,因为我认为counter=0应该在system()之外。

澄清已解决状态的答案选择注意事项:

怀疑复杂和残酷,选择我将给出的答案作为答案:

一方面,用户@Dan Answer(作者对awk上一期档号的回答)自己解释的简单性;

另一方面,答案对向user@markp-fuso学习非常有用的深化。

也许当其他用户需要阅读这个问题时,我应该考虑他们,所以我将选择如何解决markp-fuso问题。我希望了解这个问题的所有答案的作者。

推荐答案

主要问题(在标准输出上重复text/text2条目)似乎来自对awk变量k的双重使用和某些缺少的输入控件。

awk变量k正被第二次和第三次gsub(... k++ ...)调用用作自动递增索引;k绝不会重置为0(或1),因此从逻辑上讲,操作k==1测试应该只发生一次。但是...

将对k==1的每一个输入行(来自所有文件)进行测试...对于带有和不带有home_cool字符串的行都会发生这种情况;并且因为有两个k==1测试正在为每一个输入行进行验证,所以只要k==1,OP将获得双重输出(texttext2)。

还请记住,对于字符串为home_cool的行,k只会递增(通过gsub()调用);没有home_cool的行将看到不变的k==1,因此两个k==1测试也将为这些行触发;我们将在标准输出上获得额外的text/text2条目,直到下一次gsub()触发并递增k(通过k++)


我建议使用不同的变量(例如,p)来确定何时打印text/text2条目,并将k==1测试(现在为if (p))移动到仅在适当的时候运行的位置。

重写的一个想法:

awk '
FNR==1 {++f; p=1}                                     # reset our "p"rintme? flag for each new file

f==1 {a[i++]=$0}

f==2 {if ($0~/home_cool/)
         {gsub(/home_cool/, a[int(j++/2)%2]) }
      print > "2.txt"
     }

f==3 {if ($0~/home_cool/)
         {gsub(/home_cool/, a[int(k++/2)%3 + 2])}
      if (p)                                          # old "k==1" test; if "p"rintme flag set then ...
         {print "text"; system("sleep 4"); p=0}       # print, sleep, clear flag
      print > "3.txt"                            
     }

f==4 {if ($0~/home_cool/) 
         {gsub(/home_cool/, a[int(k++/2)%3 + 2])}
      if (p)                                          # old "k==1" test; if "p"rintme flag set then ...
         {print "text2"; system("sleep 4"); p=0}      # print, sleep, clear flag
      print > "4.txt"
     }
' 1.txt 0.txt 0-1.txt 0-2.txt

运行时,这将在标准输出上生成以下内容:

text
text2

备注:

  • 除了打印问题,我假设op的逻辑是正确的(即[234].txt文件的内容是正确的)
  • 如果输入文件为空,则关联的f==?测试将不会触发,这意味着...
  • 关联的if (p)...测试/操作将不会触发;
  • 例如...
  • 如果0-2.txt为空,则f==4永远不会检测为阳性,因此...
  • 关联的if (p) ... print "text2" ...将不会触发
  • 我不清楚,如果相应的文件为空,OP是否需要有条件地打印text/text2消息...
  • 修改代码很容易,但我现在跳过这一步,以减少混淆

这篇关于使用system()在Awk中只运行一次外壳命令,即只打印一次文本(&q;)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆