Command grouping (&&, ||, …)

江枫思渺然 提交于 2020-08-19 04:20:52

问题


We are currently in the /home/student/ directory. We execute the following commands:

pwd; (ls) || { cd .. && ls student/; }  && cd student || cd / && cd ;

The commands that are executed are: pwd, ls, cd student, cd /, cd

Here is what I think:

  • pwd is executed, because it's the first command

  • (ls) is executed in a subshell, because the commands are seperated
    with ";"

  • the code on the right of || isn't executed, since the code on the
    left of || was executed

So far everything clear, I guess. But I have no idea why other commands are executed? If someone could break it down for me, I'd appreciate it.


回答1:


Operator precedence for && and || is strictly left-to-right.

Thus:

pwd; (ls) || { cd .. && ls student/; }  && cd student || cd / && cd ;

...is equivalent to...

pwd; { { { (ls) || { cd .. && ls student/; }; } && cd student; } || cd /; } && cd ; }

...breaking that down graphically:

pwd; {                                      # 1
       {                                    # 2
         { (ls) ||                          # 3
                   { cd .. &&               # 4
                              ls student/;  # 5
                   };                       # 6
         } && cd student;                   # 7
       } || cd /;                           # 8
     } && cd ;                              # 9
  1. pwd happens unconditionally
  2. (Grouping only)
  3. ls happens (in a subshell) unconditionally.
  4. cd .. happens if (3) failed.
  5. ls student/ happens if (3) failed and (4) succeeded
  6. (Grouping only)
  7. cd student happens if either (3) succeeded or both (4) and (5) succeeded.
  8. cd / happens if either [both (3) and one of (4) or (5) failed], or [(7) failed].
  9. cd happens if (7) occurred and succeeded, or (8) occurred and succeeded.

Using explicit grouping operators is wise to avoid confusing yourself. Avoiding writing code as hard to read as this is even wiser.




回答2:


(ls) is executed in a subshell, because the commands are seperated with ";"

ls is executed in a subshell because of the parentheses. Parentheses introduce subshells.

But I have no idea why other commands are executed?

Unlike other programming languages you might be familiar with, bash does not give && higher precedence than ||. They have equal precedence and are evaluated from left to right.

If you had a || b && c, in other languages this would be read as a || {b && c;}. If a were true then neither b nor c would be evaluated.

In bash, though, it's parsed as {a || b;} && c (strict left-to-right precedence), so when a is true b is skipped but c is still evaluated.



来源:https://stackoverflow.com/questions/29351665/command-grouping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!