是否禁止在"for NAME"中使用NAME后的分号...? [英] Is a semicolon prohibited after NAME in `for NAME do ...`?

查看:123
本文介绍了是否禁止在"for NAME"中使用NAME后的分号...?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

bash手册将for复合语句的语法列出为

The bash manual lists the syntax for the for compound statement as

for name [ [ in [ word ... ] ] ; ] do list ; done

for name [ [ in [ word ... ] ] ; ] do list ; done

表示如果省略 in 子句,则 do 前的分号是可选的. [笔记2].

which implies that the semicolon before do is optional if the in clause is omitted. [Note 2].

但是,Posix规范仅列出了for_clause的以下三种产品:

However, the Posix specification lists only the following three productions for for_clause:

for_clause       : For name linebreak                            do_group
                 | For name linebreak in          sequential_sep do_group
                 | For name linebreak in wordlist sequential_sep do_group
                 ;

作为参考,linebreakNEWLINE的可能为空的序列,而sequential_sep是分号或NEWLINE的可能,随后可能是NEWLINE的序列:

For reference, linebreak is a possibly-empty sequence of NEWLINE while sequential_sep is either a semicolon or a NEWLINE, possibly followed by a sequence of NEWLINE:

newline_list     :              NEWLINE
                 | newline_list NEWLINE
                 ;
linebreak        : newline_list
                 | /* empty */
                 ;
separator        : separator_op linebreak
                 | newline_list
                 ;
sequential_sep   : ';' linebreak
                 | newline_list
                 ;

据我所知,它禁止使用语法for foo; do :; done.

As far as I can see, that prohibits the syntax for foo; do :; done.

实际上,我尝试过的所有shell(bash,dash,ksh和zsh)都可以接受for foo; do :; donefor foo do :; done,而无需抱怨,无论Posix或自己的文档如何[注3].

In practice, all the shells I tried (bash, dash, ksh and zsh) accept both for foo; do :; done and for foo do :; done without complaint, regardless of Posix or their own documentation [Note 3].

这是Posix标准在语法上的偶然遗漏吗?还是应该在该语法中使用分号被视为对标准的(通常实现的)扩展?

Is this an accidental omission in the grammar in the Posix standard, or should the use of the semicolon in that syntax be considered a (commonly-implemented) extension to the standard?

for loop的XCU描述中,Posix似乎坚持换行:

In the XCU description of the for loop, Posix seems to insist on newlines:

for 循环的格式如下:

The format for the for loop is as follows:

for name [ in [word ... ]]
do
compound-list
done

for name [ in [word ... ]]
do
compound-list
done

但是,在基本原理"卷中清楚地表明,语法旨在成为硬道理:

However, in the Rationale volume, it is made clear that the grammar is intended to be the last word:

格式显示时经常使用< newline>人物.有关< newline>位置的详细说明,请参见XCU Shell语法中的语法.和<分号>字符可以互换.

The format is shown with generous usage of <newline> characters. See the grammar in XCU Shell Grammar for a precise description of where <newline> and <semicolon> characters can be interchanged.


注释

  1. 显然,这是第一个将的问题,可能更合适.

  1. Apparently this is the first SO question which pairs shell and language-lawyer. There is no idle-curiosity, which might have been more appropriate.

bash手册对换行符并不十分明确;它说的是:

The bash manual is not entirely explicit about newlines; what it says is:

在大多数情况下,命令描述中的 list 可能与命令的其余部分之间用一个或多个换行符分隔,并且可能会在换行符后用分号代替.

In most cases a list in a command's description may be separated from the rest of the command by one or more newlines, and may be followed by a newline in place of a semicolon.

很明显,可以用换行符替换 done 之前的分号,但是似乎没有提到可以对 .

That makes it clear that the semicolon preceding done can be replaced by a newline, but does not seem to mention that the same transformation can be performed on the semicolon preceding do.

kshzsh似乎都坚持在name之后使用分号或换行符,尽管实现方式并不坚持使用分号或换行符.

Both ksh and zsh seem to insist that there be either a semicolon or a newline after the name, although the implementations don't insist on it.

ksh联机帮助页列出了以下语法:

The ksh manpage lists the syntax as:

for vname [ in word ... ] ;do list ;done

for vname [ in word ... ] ;do list ;done

(我相信;do;done中的分号代表分号或换行符".我无法找到任何明确的声明来表示这种效果,但这是理解语法描述的唯一方法)

(I believe that the semicolon in ;do and ;done represents "a semicolon or a newline". I can't find any definite statement to that effect but it is the only way to make sense of the syntax description.)

zsh手册显示:

for name ... [ in word ... ] term do list done
   其中 term 是至少一个换行符或; .

for name ... [ in word ... ] term do list done
    where term is at least one newline or ;.

推荐答案

很漂亮!我没有确切的答案,但这是源代码对此的解释:

Nicely spotted! I don't have a definite answer, but here is what the source code says about it:

来自AT& T UNIX v7的原始Bourne shell :

(shell has just read `for name`):
       IF skipnl()==INSYM
       THEN chkword();
        t->forlst=item(0);
        IF wdval!=NL ANDF wdval!=';'
        THEN    synbad();
        FI
        chkpr(wdval); skipnl();
       FI
       chksym(DOSYM|BRSYM);

鉴于此摘要,这似乎不是一个有意识的设计决定.这只是将分号作为in组的一部分来处理的副作用,当没有"in"时,会完全跳过分号.

Given this snippet, it does not appear to be a conscious design decision. It's just a side effect of the semicolon being handled as part of the in group, which is skipped entirely when there is no "in".

Dash同意无效在伯恩(Bourne)中,但将其添加为扩展名:

Dash agrees that it's not valid in Bourne, but adds it as an extension:

        /*
         * Newline or semicolon here is optional (but note
         * that the original Bourne shell only allowed NL).
         */

Ksh93 声称它是有效的,但未提及上下文:

Ksh93 claims that it's valid, but says nothing of the context:

/* 'for i;do cmd' is valid syntax */
else if(tok==';')
    while((tok=sh_lex(lexp))==NL);

Bash没有评论,但明确添加了对这种情况:

Bash has no comment, but explicitly adds support for this case:

for_command:    FOR WORD newline_list DO compound_list DONE
            {
              $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
              if (word_top > 0) word_top--;
            }
...
    |   FOR WORD ';' newline_list DO compound_list DONE
            {
              $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
              if (word_top > 0) word_top--;
            }

在zsh中,它只是的副作用解析器:

while (tok == SEPER)
    zshlex();

其中(SEPER ;或换行).因此,zsh很高兴接受此循环:

where (SEPER is ; or linefeed). Due to this, zsh happily accepts this loop:

for foo; ; 
;
; ; ; ; ;
; do echo cow; done

对我来说,所有这些都表明POSIX中的故意遗漏,并且作为扩展被广泛而有意地支持.

To me, this all points to an intentional omission in POSIX, and widely and intentionally supported as an extension.

这篇关于是否禁止在"for NAME"中使用NAME后的分号...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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