简体   繁体   English

我在 bash 脚本中使用 perl 来传递到正则表达式。 如何在管道 stream 中设置变量?

[英]I use perl in a bash script that pipes to a regular expression. How do I also set a variable in the piped stream?

I have created a bash script that runs on several machines that contain different git local repositories.我创建了一个 bash 脚本,该脚本在包含不同 git 本地存储库的多台机器上运行。 It tests many conditions and tells me if the repository has uncommitted files, untracked files, and one test in particular tells me that the local is ahead or behind the remote by the number of commits.它测试了许多条件并告诉我存储库是否有未提交的文件、未跟踪的文件,特别是一项测试告诉我本地在提交数量上领先还是落后于远程。 The problem with the script is that it doesn't return or set an 'ok' flag which I use to echo the "ok" message if everything is in sync.脚本的问题是它没有返回或设置一个“ok”标志,如果一切都同步,我用它来回显“ok”消息。 So, I get the message that it's ahead or behind, but then get the "ok" message.所以,我得到它领先或落后的消息,但随后得到“ok”消息。 Here is the portion of the script that does the ahead or behind, and I can't see how to get it to set an ok = false somehow.这是执行前面或后面的脚本部分,我看不出如何让它以某种方式设置 ok = false 。

   git fetch>/dev/null && git branch -v |
        perl -wlne'
           print "$ENV{reponame} [$1] --> $3 $2"
              if /^..(\S+)\s+([a-f0-9]+)\s+(\[(?:ahead|behind)\s+\d+\])/
        ' |
        while IFS= read -r MOD; do
           ok=false
           printf ' %s\n' "$MOD"  # Replace with code that uses $MOD
        done
        if $ok; then
              echo " OK --> $reponame [$br] $rev"
        fi 

I copied this from another script and don't really understand the IFS = read -r MOD;我从另一个脚本中复制了这个,并不真正理解 IFS = read -r MOD; section that I thought might set the flag, but it doesn't occur.我认为可能会设置标志的部分,但它没有发生。

This is the output I get:这是我得到的 output:

 bin [develop] --> [behind 1] 026e1ad
 OK --> bin [develop] 026e1ad
 OK --> notes [develop] 4cd077f
 OK --> indecks [develop] e6b4293
 OK --> queue [develop] 5469679
 OK --> frameworks [master] 05fedb6
 OK --> dashboard [isolate] f8b1101
 OK --> nodejs [develop] 5af2ea7
 OK --> perl-forth [master] 45cc837
 OK --> blog [master] c19edfd

Note that for bin I get:请注意,对于 bin 我得到:

 bin [develop] --> [behind 1] 026e1ad
 OK --> bin [develop] 026e1ad

I'd rather not get that OK after the behind 1. Another script checks for any non-OK in the left column and sends me an email.在后面 1 之后,我宁愿没有得到那个 OK。另一个脚本检查左列中的任何非 OK 并向我发送电子邮件。

With the perl and all the piping, how could I set the ok variable before it prints?使用 perl 和所有管道,如何在打印之前设置 ok 变量?

In most shell implementations, all processes in a pipeline are run in a subshell.在大多数 shell 实现中,管道中的所有进程都在子 shell 中运行。 In this case, you're running a while loop at the end of a pipeline, so it (and it alone) is in the subshell.在这种情况下,您在管道末端运行了一个 while 循环,因此它(并且仅它一个)位于子 shell 中。 Whether you set ok to false or not, it has no effect on the if block because that's run the main shell, which doesn't inherit variables from the subshell.无论您是否将ok设置为false ,它对 if 块都没有影响,因为它运行的是主 shell,它不会从子 shell 继承变量。

zsh and AT&T ksh (but not other ksh implementations) execute the last command in the main shell and not a subshell. zsh 和 AT&T ksh(但不是其他 ksh 实现)在主 shell 而不是子 shell 中执行最后一个命令。 POSIX permits either behavior, but the bash behavior is far more common among shells. POSIX 允许任何一种行为,但 bash 行为在 shell 中更为常见。

The easiest way to handle this is to run the entire command you're interested in in a subshell:处理此问题的最简单方法是在子 shell 中运行您感兴趣的整个命令:

  git fetch>/dev/null && git branch -v |
        perl -wlne'
           print "$ENV{reponame} [$1] --> $3 $2"
              if /^..(\S+)\s+([a-f0-9]+)\s+(\[(?:ahead|behind)\s+\d+\])/
        ' |
        (while IFS= read -r MOD; do
           ok=false
           printf ' %s\n' "$MOD"  # Replace with code that uses $MOD
        done
        if $ok; then
              echo " OK --> $reponame [$br] $rev"
        fi) 

This puts both parts using the ok variable in the same subshell, so you can modify it and it will have an effect.这会将使用ok变量的两个部分放在同一个子 shell 中,因此您可以对其进行修改,它会产生效果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM