使用 PHP 开发的同学多少都会接触过 CLI 命令行。经常会有一些定时任务或者一些脚本直接使用命令行处理会更加的方便,有些时候我们会需要像网页的 GET 、 POST 一样为这些命令行脚本提供参数。比如在针对某些日期做统计的脚本,就需要传递一个日期给它,这样我们就统计指定日期的一些数据。这类需求应该非常常见,那么,我们都是如何来接收这些命令行的参数的呢?今天,就来介绍一下这方面的内容。

$argv 获得所有空格分隔的参数列表

这个变量估计是大家用得比较多的一个接参变量了。它是 PHP 为我们准备好的一个固定变量,目的就是获取传递给脚本的参数数组。

print_r($argv);
// php 如何获取PHP命令行参数.php --a=1 -b=2 -c=3 -d=4 --e=5 ccc ddd
// Array
// (
// [0] => 如何获取PHP命令行参数.php
// [1] => --a=1
// [2] => -b=2
// [3] => -c=3
// [4] => -d=4
// [5] => --e=5
// [6] => ccc
// [7] => ddd
// )

这个数组是以参数间隔的空格进行分隔的。第1个元素是当前运行的脚本文件名,也就是说,不管有没有参数,这个变量一定会有一个 $argv[0] 表示的是当前的脚本文件名。

在日常的开发需求中,其实使用这个变量就已经够用了。但是这明显不会是我们今天的主题,大家注意到上面的代码中我们有很多参数是 -x=xxx 的形式,这种形式的参数是不是和 Linux 的命令选项非常像,没错,这就是我们今天要重点介绍的:从命令行参数列表中获取选项。

getopt() 从命令行参数列表中获取选项

其实就是这样一个简单的函数,我们就可以像 Linux 的命令选项一样获取指定的命令值。而且不是像 $argv 按空格进行分隔,命令选项函数会将这些命令选项封装成数组,组成以选项名为键,以等号后面的内容为值的数组,更加方便我们的使用。

// php 如何获取PHP命令行参数.php --a=1 -b=2 -c=3 -d=4 --e=5 ccc ddd
print_r(getopt('a:b:c:d:e:f:'));
// Array
// (
// [b] => 2
// [c] => 3
// [d] => 4
// )

是不是很神奇,而且非常直观吧,我们直接就拿到了 b 、 c 、d 的内容并且是格式非常清晰的键值数组形式。有同学要问了,a 和 e 呢?还有后面的 ccc 、 ddd 呢?

首先要说明的是,ccc 和 ddd 不是标准的选项参数,也就是说,这个函数接收的内容是以 - 开头的选项,所以 ccc 和 ddd 不会在这里输出,并且需要注意的是,非选项参数会中断选项参数的获取,在 ccc 之后如果继续添加 - 开头的选项也是无法获取到的,这个我们后面还会看到。而 -- 开头的选项参数呢?我们直接看下面的长选项功能。

长选项

// php 如何获取PHP命令行参数.php --a=1 -b=2 -c=3 -d=4 --e=5 ccc ddd
print_r(getopt('', ['a:','b:','c:','d:','e:','f:']));
// Array
// (
// [a] => 1
// [e] => 5
// )

没错,getopt() 函数的第二个参数就是定义这种 -- 开头的长选项的,而且需要注意的是,第一个参数是字符串类型,第二个长选项参数是数组类型的。那么我们把它们结合起来,就当然可以获取到全部的参数信息啦!

// php 如何获取PHP命令行参数.php --a=1 -b=2 -c=3 -d=4 --e=5 ccc ddd
print_r(getopt('a:b:c:d:e:f:', ['a:','b:','c:','d:','e:','f:']));
// Array
// (
// [a] => 1
// [b] => 2
// [c] => 3
// [d] => 4
// [e] => 5
// )

OK,参数选项获取没问题了吧,细心的同学肯定又发现了一个问题,这个 getopt() 函数的参数中定义的选项名称后面为啥都要加个冒号?这就涉及到我们的冒号规则了,请直接往下看。

冒号规则

getopt() 的前两个参数都支持一套关于选项获取的规则:

  • 单独的字符(不接受值)
  • 后面跟随冒号的字符(此选项需要值)
  • 后面跟随两个冒号的字符(此选项的值可选)

我们还是直接通过代码来看一下。

// 一
// php 如何获取PHP命令行参数.php --a=1 -b=2 -c=3 -d=4 --e=5 ccc ddd
print_r(getopt('abcdef'));
// Array
// (
// [b] =>
// [c] =>
// [d] =>
// ) // 二
// php 如何获取PHP命令行参数.php -f
print_r(getopt('f::'));
// Array
// (
// [f] =>
// )
print_r(getopt('f:'));
// Array
// (
// ) // 三
// php 如何获取PHP命令行参数.php -f 22
print_r(getopt('f::'));
// Array
// (
// [f] =>
// )
print_r(getopt('f:'));
// Array
// (
// [f] => 22
// ) // 四
// php 如何获取PHP命令行参数.php -f=22
print_r(getopt('f::'));
// Array
// (
// [f] => 22
// )
print_r(getopt('f:'));
// Array
// (
// [f] => 22
// )

这一段比较长,我们一块一块来看。首先是不带冒号的 abcdef 写法,返回的数组中都包含键,但没有值,对应上面的规则就是不接受这些参数选项的值,你传了这些参数选项也是只有键名而内容是空的。

第二段是定义了一个参数,但是不给值,这时,双冒号 :: 会有键名,而单冒号 : 则什么都没有。

第三段是空格形式的选项值,双冒号 :: 有键名但没有值,单冒号 : 键值正常。

第四段是等号 = 形式的选项值,单双冒号都正常接收到键值。

选项参数中断

上文中我们提到过参数中断的问题,就是在选项参数之后如果有一个非选项参数的参数出现,getopt() 就无法再获取到这个非选项参数后面的所有内容了。

// php 如何获取PHP命令行参数.php -f=22 aa -b=33
// 选项的解析会终止于找到的第一个非选项,之后的任何东西都会被丢弃。
// Array
// (
// [f] => 22
// )

通过这个测试可以清晰的看出后面的 b 选项无法获取。这时,如果我们想知道选项参数在什么地方或者因为哪个参数而中断的话,就可以使用 getopt() 函数的第三个参数了。

// php 如何获取PHP命令行参数.php -f=22 aa -b=33
$optind = null;
getopt('f:b:', [], $optind);
echo $optind, PHP_EOL; // 返回中断位置的索引值,2
echo $argv[$optind], PHP_EOL; // 等同于 $argv 的索引顺序,aa

注释已经写得很清晰了,第三个参数会回调一个参数选项中断位置的索引,并且这个索引是和 $argv 的索引顺序位置一致的。

总结

说实话,在没看文档前真的只知道有一个 $argv 变量可以用来获取命令行脚本的参数,通过这次学习才发现原来还有一个这么强大的选项参数函数。学习的过程非常简单,如何运用到真实的项目中才是关键所在,加油学习,努力实践吧!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96PHP%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0.php

参考文档:

https://www.php.net/manual/zh/reserved.variables.argv.php

https://www.php.net/manual/zh/function.getopt.php

如何获取PHP命令行参数的更多相关文章

  1. [Gradle] 获取 gradle 命令行参数

    project.gradle.startParameter 参考 StartParameter | Gradle API 4.9

  2. UE4命令行参数解析

    转自:https://blog.csdn.net/u012999985/article/details/53544389 一 .命令行参数简述命令行参数是一连串的关键字字符串,当运行可执行文件时可以通 ...

  3. Golang: 打印命令行参数

    记得最早在学校机房学习 Java 时,照着书上的例子,写一个最简单 main 方法,当程序运行并在屏幕上打印出 hello world 时,内心竟有种莫名的激动,相信很多人都有这种经历吧. 不管学什么 ...

  4. 命令行参数 && json 协议 && 自定义 error 类型

    命令行参数 在写代码的时候,在运行程序做一些初始化操作的时候,往往会通过命令行传参数到程序中,那么就会用到命令行参数 例如,指定程序运行的模式和级别: go run HTTPServer.go --m ...

  5. Delphi 获取进程路径及命令行参数

    Delphi 获取进程路径及命令行参数, 但有的进程获取时会报错,不知为啥 type PVOID64 = UINT64; _UNICODE_STRING = packed record Length ...

  6. C#中如何获取其他进程的命令行参数 ( How to get other processes's command line argument )

    Subject: C#中如何获取其他进程的命令行参数 ( How to get other processes's command line argument )From: jian ...

  7. [Go] gocron源码阅读-flag包实现命令行参数获取

    调用flag包可以方便的获取到命令行中传递的参数,比如可以实现类似nginx执行程序获取命令行参数执行不同操作的目标 package main import ( "flag" &q ...

  8. pytest动态添加命令行参数并获取(钩子函数:pytest_addoption)

    考虑场景: 我们的自动化用例需要支持在不同测试环境运行,有时候在dev环境运行,有时候在test环境运行: 有时候需要根据某个参数不同的参数值,执行不同的业务逻辑: 上面的场景我们都可以通过" ...

  9. Python_sys.argv 命令行参数获取使用方法

    import sys print(sys.argv) """ 获取命令行参数 输入 python3 sys.argv_demo.py 输出: ['argv.py'] 输入 ...

随机推荐

  1. Vue系列-04-项目1

    路飞学城项目 项目搭建 创建项目目录 # cd 项目目录 # vue init webpack luffy 效果 根据上面的提示,我们已经把vue项目构建好了,接下来我们可以在vscode编辑器中把项 ...

  2. sqli-labs lesson 24-25a

    less 24: 注意一开始登录后出现无法返回或者跳转页面的话是因为一开始解压sqli-labs文件时出现 logged-in.php文件不正确同名文件有问题. 直接重新解压一边全部替换掉所有文件即可 ...

  3. DVWA-全等级文件包含

    DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法 ...

  4. hdmi 随笔

    从图片来看,每张图片开始传输的是45像素的垂直同步, 1.控制数据贯穿所有时间,没个不是控制数据的传输都被控制数据包围.控制数据还要通过控制位指示,下一个数据是数据岛还是视频信号. 2.terc4 全 ...

  5. SpringBoot Spring Security 核心组件 认证流程 用户权限信息获取详细讲解

    前言 Spring Security 是一个安全框架, 可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障, 每一个 web 请求都先要经过 Sprin ...

  6. c# 对 struct为什么不能继承类和结构的思考

    1.类.结构在使用的时候可以不调用构造函数,如果能够继承类,这种情况下不能够初始化基类,因为不执行构造函数 2.结构.所有的结构类型都默认是 sealed,通过 反汇编可以看到  ,这就阻止了结构被继 ...

  7. vs2019 实现C#调用c++的dll两种方法

    1.托管与非托管的区别 2.非托管类的实现 第一步:创建C++空项目(命名Caculate)添加一个类AddOperate 第二步:将C++代码编译成动态库dll 第三步:将dll拷贝到c#项目输入目 ...

  8. C++继承体系中的内存对齐

    本篇随笔讨论一个比较冷门的知识,继承结构中内存对齐的问题,如今内存越来越大也越来越便宜,大部分人都已经不再关注内存对齐的问题了.但是作为一个有追求的技术人员,实现功能永远都是最基本的要求,把代码优化到 ...

  9. TiDB基本简介

    一.TiDB整体架构 与传统的单机数据库相比,TiDB具有以下优势: 纯分布式架构,拥有良好的扩展性,支持弹性的扩缩容 支持SQL,对外暴露MySQL的网络协议,并兼容大多数MySQL的语法,在大多数 ...

  10. Python代码阅读(第2篇):数字转化成列表

    本篇阅读的代码实现了将输入的数字转化成一个列表,输入数字中的每一位按照从左到右的顺序成为列表中的一项. 本篇阅读的代码片段来自于30-seconds-of-python. digitize def d ...