已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > PHP > 讨论/求助

标题: 为什么 echo 很特殊

作者: @Ta

时间: 2022-08-22

点击: 14844

image.png(19.79 KB)

Parse error: syntax error, unexpected 'echo' (T_ECHO) in /www/app1/public/test.php on line 20


若把最后一行改成 vardump,print_f  ||  function() 等 函数形式就行  echo echo()等不可以

[隐藏样式|查看源码]


『回复列表(52|隐藏机器人聊天)』

3.

echo是一个没有返回值的语言结构,就算加括号也不能改变这一点。

因为没有返回值,所以无法用于a || b表达式。这和函数不同,函数总是有返回值,函数不加return的情况下只是返回null,不像echo完全没有返回值。因为完全没有返回值,所以任何尝试捕获其返回值的表达式都会语法错误。

要让a || echo 'xxx'成立,echo 'xxx'必须有返回值,因为该表达式的本义是求aecho 'xxx'的逻辑或值,而||的右侧不可求值,所以语法错误。

想要用于a || b表达式,可以改用print(有返回值的语言结构)或printf(普通函数)。

https://php.net/echo
https://php.net/print
https://php.net/printf

$a['k1'] || print('ok');

从上面可以看出,PHP中的a || b表达式并不是if (!a) b的良好替代品,因为这么用完全依赖语句的“副作用”,是当a为假时,需要对b求值,所以才执行了b的代码。而如果b不可求值,代码就会语法错误。

(/@Ta/2022-08-22 15:08//)

4.

估计是和if之类同级别的某种语法吧,而不是函数。在语法分析里会有单独的分支。

感觉早期编程语言容易出现特殊语法。比如:

Visual Basic

Mid(Str, 2, 3) = "替换"                                    ' 将 Str 第 2 ~ 4 个字符替换为“替换”
Name "C:\旧路径\旧文件.txt" As "C:\新文件.txt"              ' 移动文件
Open "C:\文件.bin" For Binary Access Read Lock Read As #1  ' 二进制模式独占打开文件
Print Spc(3); "hello"; Tab(15); ; ; ; "world"              ' 空 3 格,输出 hello,再定位至 15 列,输出 world
PSet (15, 20), &HFF                                        ' 在 x = 15, y = 20 处画个红色的点
Line (15, 20)-(30, 45), vbBlue                             ' 画条蓝色的线
Line (15, 20)-Step(10, 10), vbGreen, B                     ' 在 x = 15, y = 20 处,画个绿色的,10 x 10 的框框
Line (15, 20)-Step(10, 10), vbGreen, BF                    ' 在 x = 15, y = 20 处,画个绿色的,10 x 10 的实心框框

SQL

SELECT CAST(... AS ...),
       DATE_ADD(..., INTERVAL ... DAY),
       EXTRACT(DAY_MINUTE FROM ...),
  FROM JSON_TABLE(
         ...,
         "$[*]"
         COLUMNS(
           rowid FOR ORDINALITY,
           a VARCHAR(10) PATH "$.a" DEFAULT '123' ON EMPTY DEFAULT '456' ON ERROR,
           b JSON PATH "$.b" DEFAULT '{"key": 789}' ON EMPTY,
           c INT EXISTS PATH "$.c"
         )
       ) AS tt;
(/@Ta/2022-08-22 14:59//)

5.

echo具有返回值从而可以用于a || b表达式并不难(print就可以),但是会影响性能。所以PHP选择保持echo无返回值(于是不能用于求值表达式,比如a || ba && b),并且添加了单独的print语言结构用于这类场景。

print语言结构之所以“总是返回1”,就是因为它的应用场景要求它必须有一个返回值,而且最好是真值。

如果print返回0,以下代码不能按预期运行:

do() && print('ok') || print('fail');

https://php.net/print

(/@Ta/2022-08-22 15:17//)

6.

@老虎会游泳,我上次生成2亿行数字,用的好像是echo吧,感觉也不是很快啊

PythonC正常的print/printf速度也不慢

感觉没必要做成特殊语法结构

(/@Ta/2022-08-22 15:17//)

7.

@无名啊,不,你用的是printf。如果你用echo,可能会快很多。

<?php
mt_srand(strtotime('2022-08-11 20:00:00'));

foreach ([STDOUT, STDERR] as $fp)
            for ($uid = 1; $uid <= 10000000; ++$uid)
                            for ($i = mt_rand(15, 25); $i > 0; --$i)
                                                fprintf($fp, "%d,%d\n", $uid, mt_rand(0, 255));
(/@Ta/2022-08-22 15:19//)

8.

@老虎会游泳,我试试用echo

(/@Ta/2022-08-22 15:22//)

9.

@老虎会游泳,也不知道Visual Basic怎么做的词法分析,有些关键词可做变量名,有些不可
无标题.png(137.36 KB)

(/@Ta/2022-08-22 15:27//)

10.

@无名啊,测试结果很有趣,echo比printf慢,多参数echo的性能取决于参数个数。

Screenshot_20220822_153907.jpg(407.95 KB)

单参数echo也比print慢。

Screenshot_20220822_154318.jpg(284.58 KB)

还有,终端是有瓶颈的,如果不重定向到文件,一分钟也完不成。

(/@Ta/2022-08-22 15:44//)

11.

@老虎会游泳

测试源码

<?php
mt_srand(strtotime('2022-08-11 20:00:00'));

for ($uid = 1; $uid <= 10000000; ++$uid)
    for ($i = mt_rand(15, 25); $i > 0; --$i)
        ...

echo $uid . ',' . mt_rand(0, 255) . "\n";

$ time php main.php > /dev/null

real    8m41.194s
user    2m50.391s
sys     5m50.391s

printf($uid . ',' . mt_rand(0, 255) . "\n");

$ time php main.php > /dev/null

real    9m39.083s
user    3m15.938s
sys     6m23.078s

PHP版本

$ php --version
PHP 8.1.5 (cli) (built: May 16 2022 17:15:25) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.5, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.5, Copyright (c), by Zend Technologies
    with Xdebug v3.1.2, Copyright (c) 2002-2021, by Derick Rethans
(/@Ta/2022-08-22 15:54//)

12.

@老虎会游泳,上面有点乱,重新写成个shell,减少数据量来测试:

结论

  1. 单参数echo和有格式化参数的printf几乎一样快
  2. printf直接输出稍慢一点点儿 (扫描参数字符串导致的慢?)
  3. 多参数echo非常慢,4倍耗时左右

测试结果

<echo $uid . ',' . mt_rand(0, 255) . "\n">
2000232 18919812

real    0m5.687s
user    0m1.984s
sys     0m9.078s

<echo $uid , ',' , mt_rand(0, 255) , "\n">
2000232 18919812

real    0m22.305s
user    0m8.547s
sys     0m35.875s

<printf($uid . ',' . mt_rand(0, 255) . "\n")>
2000232 18919812

real    0m5.817s
user    0m2.484s
sys     0m8.563s

<printf("%d,%d\n", $uid, mt_rand(0, 255))>
2000232 18919812

real    0m5.694s
user    0m2.172s
sys     0m9.000s

bash源码

while read -r code; do

    echo $'\n'"<$code>"
    time php <<-EOF | wc -lc
        <?php
        mt_srand(strtotime('2022-08-11 20:00:00'));

        for (\$uid = 1; \$uid <= 100000; ++\$uid)
            for (\$i = mt_rand(15, 25); \$i > 0; --\$i)
                $code;
EOF

done <<-'EOF'
    echo $uid . ',' . mt_rand(0, 255) . "\n"
    echo $uid , ',' , mt_rand(0, 255) , "\n"
    printf($uid . ',' . mt_rand(0, 255) . "\n")
    printf("%d,%d\n", $uid, mt_rand(0, 255))
EOF
(/@Ta/2022-08-22 17:25//)

13.

@无名啊,我这边printf("%d,%d\n", $uid, mt_rand(0, 255))是最快的。搞不懂。

PHP 8.1.6 (cli) (built: Jun 7 2022 04:09:29) (NTS)

(/@Ta/2022-08-22 16:10//)

14.

@老虎会游泳,结论差不多,反正echo存在的必要性看来是很低了

(/@Ta/2022-08-22 16:16//)

15.

@无名啊,目前只测了CLI,在web中的情况可能不同。

(/@Ta/2022-08-22 16:20//)

16.

@老虎会游泳,你这啥手机啊,比我笔电快一倍不止,搞得笔电一点尊严都没有,好歹也是个 (低压) 8 代 i5 啊

(/@Ta/2022-08-22 16:23//)

17.

@无名啊,没什么不同,还是printf最快

Screenshot_20220822_162523_com.termux.jpg(588.56 KB)

(/@Ta/2022-08-22 16:25//)

18.

@无名啊,你的终端有瓶颈吧,你是不是在使用Windows?Windows控制台宿主(conhost.exe)的终端行处理很慢。

Screenshot_20220822_162759_com.termux.jpg(443.20 KB)

(/@Ta/2022-08-22 16:29//)

19.

@老虎会游泳,我是wsl1

(/@Ta/2022-08-22 16:29//)

20.

@无名啊,那你试试WSL2。

(/@Ta/2022-08-22 16:33//)

21.

@老虎会游泳,手机试了试,确实速度快多了
Screenshot_2022-08-22-16-34-17-151_com.termux.jpg(388.95 KB)

(/@Ta/2022-08-22 16:35//)

下一页 1/3页,共52楼

回复需要登录

8月23日 23:20 星期六

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1