根据对这个问题的先前回答,我在下面有以下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
文件后,才应执行特定的 shell 命令。
该解决方案还应该能够在创建4.txt
之前打印text2
。
我正在使用system()
,到目前为止我的尝试效果不佳,唯一不起作用的是 shell 脚本执行了 3 次而不是 1 次(这可以通过屏幕上的 3text
打印看到)。
我该怎么做才能看到真正错过了解决这个问题,并且在创建2.txt
之前只运行一次echo 'text'
?
我试图在system()
(system("counter=0; if [[ "$counter" -gt 2 ]] then echo "text" fi; sleep 4")
)内插入一个计数器(没有whil
e),但没有奏效,这真的没有多大意义,因为我相信counter=0
应该不system()
。
澄清已解决状态答案选择的说明:
疑惑复杂而残酷,选择我将给出的答案作为解决:
一方面,简单性解释了用户自己的很多@dan答案(作者对awk
中上一期文件编号的回答);
另一方面,一个非常有用的深化答案,用于向用户学习@markp-fuso。
也许我应该在其他用户需要阅读此问题时考虑他们,所以我会选择如何解决 markp-fuso 的问题。我希望了解所有回答这个问题的作者。
主要问题(在stdout上重复text/text2
条目)来自awk
变量k
的双重用途和一些缺失的输入控制。
awk
变量k
被第 2 次和第 3 次gsub(... k++ ...)
调用用作自动递增索引;在k
任何时候都不会重置为0
(或1
),因此从逻辑上讲,操作k==1
测试应该只发生一次。 然而。。。
k==1
测试将针对每个输入行(来自所有文件)进行......对于带有和不带有home_cool
字符串的行,都会发生这种情况;并且由于每个输入线有两个k==1
测试正在验证,只要k==1
,OP将获得双输出(text
和text2
)。
还要记住,对于带有字符串home_cool
的行,k
只会递增(通过gsub()
调用);最终结果是不home_cool
的行将看到k==1
不变,因此两个k==1
测试也将针对这些行触发;我们将在 stdout 上获得额外的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
消息...... - 修改代码很容易,但我现在跳过它以限制混淆
我能做些什么来查看真正错过的问题来解决这个问题并回显"文本" 在创建之前只运行一次
2.txt
?
如果您想要以下行为:仅在2.txt
不存在时才运行,然后更改
{system("echo 'text' && sleep 4")}
自
{system("ls 2.txt && echo 'text' && sleep 4")}
如果没有2.txt
ls
就会出现故障并阻止执行超出&&
的内容。请注意,ls
确实会发出输出,如果这在您的情况下不可接受,则需要添加stdout
并stderr
重定向,以便ls
到/dev/null
。
我尝试在创建 2.txt 文件后和创建 3.txt 文件之前只运行一次命令 shell。
添加一个FNR==1
的 test 作为f==3
块的第一个命令,如下所示:
f==3 {if (FNR==1) {system("##")}; if ($0~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}
它将在该块中的其他任何内容之前执行。
或者,您可以添加此pattern {action}
,直接在f==3
上方:
f==3 && FNR==1 {system("##")}
f==3 {if ($0~/home_cool/) {gsub(/home_cool/, a[int(k++/2)%3 + 2]) }; print > "3.txt"}
模式/操作块始终按给定的顺序执行,因此它将首先执行。
无论您认为哪个更具可读性。