运行 Shell Awk 内部命令仅一次 'per command' 使用 System(),即仅打印一次 "text"

Run Shell Command Inside Awk only Once 'per command' Using System(), i e, print only Once "text"

根据此处对该问题的先前回答,我有下面的 awk 脚本示例

awk \
'
FNR==1 {++f}

f==1 {a[i++]=[=14=]}
f==2 {if ([=14=]~/home_cool/) {gsub(/home_cool/, a[int(j++/2)%2]) }; print > "2.txt"}
k==1 {system("echo 'text' && sleep 4")}
f==3 {if ([=14=]~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}
k==1 {system("echo 'text2' && sleep 4")}
f==4 {if ([=14=]~/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 文件之前仅添加一次命令 shell 运行。

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

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

我正在使用 system(),到目前为止我的尝试效果不佳,唯一不起作用的是 shell 脚本执行了 3 次而不是 1 次(这可以可以看到屏幕上的 3 text 个打印件。

我该怎么做才能看到真正遗漏了什么来解决这个问题 echo 'text' 是 运行 只有一次并且在 2.txt 被创建之前?

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

说明已解决状态的答案选择:

疑惑复杂而残酷,选择我将给出的答案作为解决:

一方面是用户@dan 的回答(作者在awk 上一期的回答中的回答);

另一方面,从用户@markp-fuso 那里得到了一个非常有用的深化学习答案。

也许其他用户需要阅读这个issue的时候我应该想想,所以我会选择如何解决markp-fuso的issue。希望能理解所有回答这个问题的作者

What can I do to see what really misses to solve this and echo 'text' is run only once and before 2.txt be created?

如果您想要以下行为:仅 运行 如果 2.txt 不存在则更改

{system("echo 'text' && sleep 4")}

{system("ls 2.txt && echo 'text' && sleep 4")}

如果没有 2.txt ls 将发生故障并阻止执行超出 && 的内容。请注意,ls 确实会发出输出,如果这在您的情况下不可接受,您将需要为 ls 添加 stdoutstderr 重定向到 /dev/null

I am trying to add a command shell only one time run after creating the 2.txt file and before creating the 3.txt file.

FNR==1 添加测试,作为 f==3 块的第一个命令,如下所示:

f==3 {if (FNR==1) {system("##")}; if ([=10=]~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}

它将在该块中的任何其他内容之前执行。

或者,您可以直接在 f==3 上方添加此 pattern {action}

f==3 && FNR==1 {system("##")}
f==3 {if ([=11=]~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}

pattern/action 块总是按照给定的顺序执行,所以同样,它会先执行。

您认为哪个更具可读性。

主要问题(在 stdout 上重复 text/text2 个条目)似乎是 awk 变量 k 的双重使用和一些缺失的输入控制。

第 2 和第 3 次 gsub(... k++ ...) 调用将 awk 变量 k 用作自动递增索引; k 绝不会重置为 0(或 1),因此从逻辑上讲,OPs k==1 测试应该只发生一次。然而...

k==1 的测试将针对每个输入行(来自所有文件)发生...这发生在有和没有 home_cool 字符串的行;并且因为有两个 k==1 测试正在为每个输入行验证 OP 将获得双输出(texttext2)只要 k==1.

另外请记住,k 仅针对字符串 home_cool 的行递增(通过 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++]=[=10=]}

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

f==3 {if ([=10=]~/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 ([=10=]~/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)... test/operation 不会触发;
  • 例如...
  • 如果 0-2.txt 为空,则 f==4 永远不会测试为阳性,所以 ...
  • 关联的 if (p) ... print "text2" ... 不会触发
  • 不清楚(对我来说)如果相应的文件为空,OP 是否需要有条件地打印 text/text2 消息...
  • 修改代码很容易,但我现在将跳过它以减少混淆