test 命令test 为 Shell 内置命令,其通常需要与 if 语句一块使用。语法格式语法格式为 test expression, 当 test 判断 expression 为成立时,返回状态为 0,否则为非 0 值。test 命令还可以简写为 [ ], 需要在两边中括号与 expression 是有一个空格,这个空格是必须的,否则会导致语法错误。[] 的写法更加简洁,比 test 使用频率更高。我们可以简单来看示例:[root@master shell_test]# cat test1.sh #!/bin/bash// 使用中括号if test 10 -ne 1;then echo "true"else echo "false"fi[root@master shell_test]# bash test1.sh true[root@master shell_test]# cat test2.sh #!/bin/bash// 使用testif [ 10 -eq 1 ];then echo "true"else echo "false"fi[root@master shell_test]# bash test2.sh true
在我们之前章节学习了 Shell 的运算符,其中大多数运算都可以结合 test 命令来完成测试与比较操作,test 命令配合各种操作符号,不仅可以完成测试逻辑表达式,还可以进行文件,数字,字符串的比较。本文是一些常见用法的归纳总结。
test 命令操作主要配合比较运算符进行,可大体分为文件判断 / 数组比较 / 字符串判断 / 逻辑运算等。
在 Shell 中每个命令都有其应用场景,test 命令也不例外,其应用场景几乎遍布我们整个 Shell 脚本的生命周期,基本上 Shell 脚本里面都会有其身影。当我们对数值进行算术运算,当我们需要对文件进行判断,当我们需要对逻辑或字符串进行判断的时候,这些情况都需要使用 test 命令来配合运算符进行操作。
请阅读如下代码:// One.javapublic class One { public void test() { }}// Two.javapublic interface Two { void test();}// Demo.javapublic class Demo1 extends One implements Two { public void test() { }}此时,我们无法确定 Demo1 类中的 test() 方法是父类 One 中的 test 还是接口 Two 中的 test。这时我们可以使用内部类解决这个问题:public class Demo2 extends One { // 重写父类方法 @Override public void test() { System.out.println("在外部类实现了父类的test()方法"); } // 定义内部类 class InnerClass implements Two { // 重写接口方法 @Override public void test() { System.out.println("在内部类实现了接口的test()方法"); } } public static void main(String[] args) { // 实例化子类Demo2 Demo2 demo2 = new Demo2(); // 调用子类方法 demo2.test(); // 实例化子类Demo2的内部类 InnerClass innerClass = demo2.new InnerClass(); // 调用内部类方法 innerClass.test(); }}运行结果:在外部类实现了父类的test()方法在内部类实现了接口的test()方法
server { server_name location.test.com; listen 8010; location = / { return 200 "精确匹配/"; } location ~* /ma.*ch { return 200 "正则匹配/ma.*ch"; } location ~ /mat.*ch { return 200 "正则匹配/match.*"; } location = /test { return 200 "精确匹配/test"; } location ^~ /test/ { return 200 "前缀匹配/test"; } location ~ /test/he*o { return 200 "正则匹配/test/he*o"; } location / { return 200 "通配/"; }}我们按照这样的 location 规则,进行匹配实验,结果如下:# 精确匹配优先级最高$ curl http://localhost:8010/精确匹配/$ curl http://localhost:8010/test 精确匹配/test# 前缀匹配优先级高于正则匹配$ curl http://180.76.152.113:8010/test/heeo 前缀匹配/test# 正则匹配,按照顺序依次匹配,如果同时匹配两个正则,则前面的优先匹配$ curl http://180.76.152.113:8010/matxxch 正则匹配/ma.*ch# 什么都匹配不到时,最后匹配通配/$ curl http://180.76.152.113:8010/xxxxx 通配/
在 nginx.conf 中加入如下的测配置:...http { server { listen 8000; return 200 '$uri\n'; } server { listen 9001; location /test { proxy_pass http://127.0.0.1; } } server { listen 9002; location /test { proxy_pass http://127.0.0.1/xyz; } }}...启动 nginx 后,通过请求服务器的8000端口,我们可以知道请求的 uri 值,然后测试经过两种类型的 proxy_pass 配置后最后的 uri 的值。具体操作以及结果如下:# 测试8000端口显示的uri值[shen@shen ~]$ curl http://180.76.152.113:8000/test/abc/test/abc# 9001端口配置中proxy_pass后面的URL不带URI[shen@shen ~]$ curl http://180.76.152.113:9001/test/abc/test/abc# 9002端口配置中proxy_pass后面的URL带URI,会替换到匹配的/test[shen@shen ~]$ curl http://180.76.152.113:9002/test/abc/xyz/abc
window.localStorage.setItem("test",1)//设置key=test的值为1localStorage.setItem("test",1)//设置key=test的值为1,localstorage可以作为全局对象处理localStorage.test = 1//可以通过属性值的方式直接操作localstorage的key运行下面案例代码,试一试:1038
这个函数使用事务执行 SQL 语句,它是一个闭包,例如:dataBase.transaction( function(tx) { tx.executeSql( "create table if not exists test (id REAL UNIQUE, name TEXT)", [], function(tx,result){ alert('创建test表成功'); }, function(tx, error){ alert('创建test表失败:' + error.message); });});
Scrapy 框架和 Django 框架类似,先使用命令行来开启一个项目的最小工程。这里会创建 python 的虚拟环境,如果不熟悉 pyenv 工具的同学,可以参考这里的文章。# 新建scray-test目录,后续会保存scrapy项目的相关代码[root@server ~]# mkdir scrapy-test[root@server ~]# cd scrapy-test/# 安装scrapy的虚拟环境[root@server scrapy-test]# pyenv virtualenv 3.8.1 scrapy-test[root@server scrapy-test]# pyenv activate scrapy-test pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.# 使用 pip 命令安装 Scrapy 框架(scrapy-test) [root@server scrapy-test]# pip install scrapy使用命令行创建一个新的 Scrapy 项目:(scrapy-test) [root@server scrapy-test]# scrapy startproject china_pubNew Scrapy project 'china_pub', using template directory '/root/.pyenv/versions/3.8.1/envs/scrapy-test/lib/python3.8/site-packages/scrapy/templates/project', created in: /root/scrapy-test/china_pubYou can start your first spider with: cd china_pub scrapy genspider example example.com查看创建好的 Scrapy 项目的文件结构:(scrapy-test) [root@server scrapy-test]# tree ..└── china_pub ├── china_pub │ ├── __init__.py │ ├── items.py │ ├── middlewares.py │ ├── pipelines.py │ ├── __pycache__ │ ├── settings.py │ └── spiders │ ├── __init__.py │ └── __pycache__ └── scrapy.cfg我们可以看到 Scrapy 命令给我们创建的项目目录和文件,这里我们来简单分析下这些目录和文件的含义,后面在介绍 Scrapy 框架的架构图后,会对这些目录以及 Scrapy 的运行有着深刻的理解:items.py:items.py 文件中一般用于定义 Item 对象,它用来指定爬取的数据的结构;middlewares.py:中间件文件,主要是处理 request 和 response 的中间过程;pipelines.py:项目的管道文件,它会对 items.py 中里面定义的数据进行进一步的加工与处理。启用该 pipline 时需要在 settings.py 中进行配置;settings.py:项目的配置文件,比如设置处理 Item 对象的 piplines、请求头的 ‘’User-Agent" 字段、代理、Cookie等;spider 目录:主要是存放爬取的动作及解析网页数据的代码。
crawl: 使用项目中的 Spider 进行爬取,该命令要求输入启动的 spider 名称;# 命令格式, 带的参数是: [spider名称](scrapy-test) [root@server china_pub]# scrapy crawl China-Pub-Crawler# ...check:运行 contract 检查;(scrapy-test) [root@server china_pub]# scrapy check----------------------------------------------------------------------Ran 0 contracts in 0.000sOKlist:列出当前项目中所有可用的 spider;(scrapy-test) [root@server china_pub]# scrapy listChina-Pub-Crawlergenspider:在当前项目中创建 spider。该方法可以使用提前定义好的模板来生成相应的 spider,也可以自己创建 spider 源码文件;我们来看一个简单的示例:(scrapy-test) [root@server scrapy-test]# mkdir genspider(scrapy-test) [root@server scrapy-test]# cd genspider/(scrapy-test) [root@server genspider]# ls# 使用genspider命令创建spider文件(scrapy-test) [root@server genspider]# scrapy genspider qidian_yuepiao www.qidian.comCreated spider 'qidian_yuepiao' using template 'basic' (scrapy-test) [root@server genspider]# lsqidian_yuepiao.py(scrapy-test) [root@server genspider]# cat qidian_yuepiao.py import scrapyclass QidianYuepiaoSpider(scrapy.Spider): name = 'qidian_yuepiao' allowed_domains = ['www.qidian.com'] start_urls = ['http://www.qidian.com/'] def parse(self, response): pass上面的操作可以看到,我们使用 scrapy 的 genspider 生成了 spider 文件,这个 spider 文件内定义了 QidianYuepiaoSpider 这个爬虫类,爬虫名称是我们输入的第一个参数,允许的爬取域名和起始的 urls 是根据第二个参数得到的。
其中 reflect.ValueOf() 函数可以获取一个变量的值。代码示例:package mainimport ( "fmt" "reflect")func main() { test := 10 ValueOfTest := reflect.ValueOf(test) fmt.Println("变量test的值:", ValueOfTest)}第 9 行:定义一个值为 10 的变量;第 10 行:通过反射获取变量的值。执行结果:
上文中我们了解了两个反射中常用的函数,接下来,我们来学习下如何使用反射来进行一些灵活的操作,比如修改变量的值。代码示例:package mainimport ( "fmt" "reflect")func main() { test := 10 //获取test变量的地址 ValueOfTestAddr := reflect.ValueOf(&test) //获取地址存放的值 ValueOfTest := ValueOfTestAddr.Elem() //修改这个值 ValueOfTest.SetInt(100) fmt.Println("变量test的值:", test)}执行结果:使用上述操作,我们就可以在一些情况下操作其它包中的私有变量,这种操作是十分危险的,所以如非必要尽量不要使用。
在 windows 和 linux 中,操作系统提供了命令行的控制方式,用户输入命令完成任务。例如,建立一个目录,输入如下命令:C:\> mkdir test这条命令创建了一个名称为 test 的目录,字符串 ‘mkdir’ 和字符串 ‘test’ 被称为命令行参数。
在 Go 语言中提供反射的包为 reflect 包,其中reflect.Type()函数可以获取一个变量的类型。代码示例:package mainimport ( "fmt" "reflect")func main() { test := 10 typeOfTest := reflect.TypeOf(test) fmt.Println("变量test的类型:", typeOfTest)}第 9 行:定义一个值为10的变量;第 10 行:通过反射获取变量的类型。执行结果:
var request = db.transaction(["test"],"readwrite").objectStore("test").get(rollNo);//创建具备读写功能的事务request.onsuccess = function(event){ console.log("结果 : "+request.result.name); };//成功查询的回调函数
var transaction = db.transaction(["test"],"readwrite");//创建事务var objectStore = transaction.objectStore("test");var request = objectStore.get(rollNo);request.onsuccess = function(event){ console.log("Updating : "+request.result.name + " to " + name); request.result.name = name;//修改数据 objectStore.put(request.result);//执行修改};
nginx 七层方向代理处理的是 http 请求,对应的是 http 协议。如果只是转发 http 请求,可以简单使用 proxy_pass 指令即可。这和我们之前简单的反向代理示例一致。# 在转发 http 请求时,URL必须以 http 或者 https 开头 Syntax: proxy_pass URL;Default: —Context: location, if in location, limit_except在使用 prxoy_pass 指令对 http 或者 https 协议进行反向代理时,需要注意一下问题:在 URL 不携带 URI 时,会将对应的 URL 直接转发到上游服务器在 URL 携带 URI 时,会将 location 参数中匹配上的那一段替换为该URL看下面的示例配置:...http { server { listen 8000; location /test { proxy_pass http://ip:port/xyz; } } server { listen 9000; location /test { proxy_pass http://ip:port; } } }... 在代理 http 请求 http://主机ip:8000/test/abc 时,由于 proxy_pass 指令后面的 URL 带了 /xyz 这样的路径,所以转发的请求是 http:// ip:port/xyz/abc,其中匹配的 /test 已经被替换掉了。而对于第二个 http 请求 http://主机ip:9000/test/abc 时,由于 proxy_pass指令后面直接是上游服务器地址,没有带 URI,所以转发的请求为 http://ip:port/test/abc,其中匹配到的/test并没有被替换。
var transaction = db.transaction(["students"],"readwrite");//先创建事务,具有读写权限transaction.oncomplete = function(event) { console.log("Success");};transaction.onerror = function(event) { console.log("Error");}; var test = transaction.objectStore("test");test.add({rollNo: rollNo, name: name});//添加数据
在测试机器的 /root/test/web 目录下有 2 个 html 文件,分别为 web.html 和 web2.html, 没有 web3.html。我们编写如下的 server 块,监听 8013 端口。首先访问 http://主机ip:8013/web 时,根据配置情况,Nginx 首先查找是否存在 /root/test/web/web3.html 文件,没有找到会继续向下,找$uri,也就是/root/test/web 文件,不存在。继续找 KaTeX parse error: Expected 'EOF', got ',' at position 15: uri/index.html,̲即/root/test/web…uri/web1.html时文件存在,故返回/root/test/web/web1.html文件内容。如果该文件还不存在,则还会继续批评额哦@lasturi,最后返回’lasturi!'这样的字符串。而在访问 http://主机ip:8013/return_code 时,由于无法匹配静态资源,根据配置最后返回404错误码,出现 Nginx 默认的 404 错误页面。server { server_name try_files.com; listen 8013; root /root/test/; default_type text/plain; location /web { # 找/root/test/index.html # try_files /index.html try_files /web/web3.html $uri $uri/index.html $uri/web1.html @lasturi; #最后匹配这个 } location @lasturi { eturn 200 'lasturi!\n'; } location /return_code { try_files $uri $uri/index.html $uri.html =404; }}
在计算机发展的早期,编程语言提供了手动内存管理的机制,例如 C 语言,提供了用于分配和释放的函数 malloc 和 free,如下所示:#include <stdlib.h>void *malloc(size_t size);void free(void *p);函数 malloc 分配指定大小 size 的内存,返回内存的首地址函数 free 释放之前申请的内存程序员负责保证内存管理的正确性:使用 malloc 申请一块内存后,如果不再使用,需要使用 free 将其释放,示例如下:#include <stdlib.h>void test(){ void *p = malloc(10); 访问 p 指向的内存区域; free(p);}int main(){ test();}使用 malloc(10) 分配一块大小为 10 个字节的内存区域使用 free§ 释放这块内存区域如果忘记释放之前使用 malloc 申请的内存,则会导致可用内存不断减少,这种现象被称为 “内存泄漏”,示例如下:#include <stdio.h>#include <stdlib.h>void test(){ void *p = malloc(10); 访问 p 指向的内存区域;}int main(){ while (1) test();}在函数 test 中,使用 malloc 申请一块内存但是使用完毕后,忘记释放了这块内存在函数 main 中,循环调用函数 test()每次调用函数 test(),都会造成内存泄漏最终,会耗尽所有的内存
假设存在 test 目录,test 目录下的子文件和子目录如下图所示:用于测试的目录树 现在要求编写程序 listDir.py,列出 test 目录下所有的文件,listDir.py 的内容如下:import osdef listDir(dir): entries = os.listdir(dir) for entry in entries: path = os.path.join(dir, entry) print(path) if os.path.isdir(path): listDir(path)listDir('test')在第 4 行,使用 os.listdir(dir) 获取目录 dir 下的文件名列表在第 5 行,遍历该列表,entry 为子文件的文件名在第 6 行,使用 os.path.join 生成子文件的完整路径在第 7 行,打印子文件的完整路径 path在第 8 行,如果子文件是目录,递归调用 listDir 列出它的所有文件运行程序,输出结果如下:test\atest\btest\b\x.txttest\b\y.txttest\ctest\readme.txt
所谓限定头信息,指 Spring MVC 可以通过 HTTP 请求包中的消息头信息进行过滤。如下面的实例:@RequestMapping(value="/test",headers="content-type=text/*")public String test(){ ... }test() 方法只会响应请求包中的内容类型为 text/* 的请求。无论是方法限定、还是参数限定或是头信息限定,其本质都是检查请求包是否符合条件要求。
可以使用如下的命令生成一个自定义命令行处理文件:php think make:command Study test如下图所示:Tips: 若 php 没有加入环境变量,可以使用绝对路径,如 E:\php\php7.3.4nts\php think version。生成的自定义命令行文件内容如下:<?phpdeclare (strict_types = 1);namespace app\command;use think\console\Command;use think\console\Input;use think\console\input\Argument;use think\console\input\Option;use think\console\Output;class Study extends Command{ protected function configure() { // 指令配置 $this->setName('test') ->setDescription('the test command'); } protected function execute(Input $input, Output $output) { // 指令输出 $output->writeln('test'); }}
在本章节由于 test 命令与运算符配合使用,与之前运算符章节有重复,在此温故知新,通过示例来更加熟悉 test 命令及相关运算符,其是后期 Shell 脚本编写的流程框架,熟练掌握 test 命令的数值,文件,字符串与逻辑运算,使得我们编写 Shell 脚本更加得心应手。
内联的事件处理器,其 this 指向的是 DOM 节点自身。<div> <button onclick="console.log(this); console.log(this === document.querySelector('button'))">点击我</button></div>这个规则有局限性,只有最外层的 this 符合这个规则。<div> <button onclick="function test() { console.log(this) }; test();">点击我</button></div>test 函数的 this 指向的是全局对象 window。
我们知道了变量的定义方式,那么该如何使用变量呢?使用变量非常简单,只需要在定义的变量名前面添加 $ 即可使用定义的变量例如:[root@master ~]# DIR=/tmp[root@master ~]# echo $DIR/tmp在使用变量中有一种特殊情况,需要我们手动指定变量的边界是什么,此时就需要使用到 {}。[root@master ~]# STRING="hello Shell"[root@master ~]# echo "test $STRINGtest"test [root@master ~]# echo "test ${STRING}test"test hello Shelltest通过示例我们能够看出,不使用 {} 引起来变量,如果变量名后面继续有字符,Shell 无法判断我们的变量边界在哪里,我们推荐在使用变量的时候都带上 {} 减少出错的概率,并且方便我们人为识别变量的边界。
现在,让我们把 MyFirst.txt 移动到 test 文件夹中,步骤如下:鼠标右键点击想要移动的 MyFirst.txt 文件,接着在弹出的菜单中选择 Move 选项,如下图所示:此时将打开 Move Resources 窗口:我们点击需要移动到的目标文件夹 test,如下图所示:点击 OK 按钮后,文件将会被移动到我们选择的 test 文件夹中,结果如下图所示:
1. 语法jinja2 提供的 tests 可以用来在语句里对变量或表达式进行测试,语法如下:{% variable is test %}完整的 test 请参考 https://jinja.palletsprojects.com/en/master/templates/#builtin-tests,部分的 test 如下:test 名称功能defined变量是否已经定义boolean变量的类型是否是 booleaninteger变量的类型是否是 integerfloat变量的类型是否是 floatstring变量是否是 stringmapping变量的类型是否是字典sequence变量的类型是否是序列even变量是否是偶数odd变量是否是奇数lower变量是否是小写upper变量是否是大写2. jinja2 模板定义一个演示 test 功能的模板:<html>{% if number is odd %} <p> {{ number }} is odd{% else %} <p> {{ number }} is even{% endif %}{% if string is lower %} <p> {{ string }} is lower{% else %} <p> {{ string }} is upper{% endif %}</html>在第 2 行,number is odd 测试 number 是否为奇数;在第 8 行,string is lower 测试 string 是否为小写。3. jinja2 的模板输入number = 404string = 'HELLO'4. 渲染后的 html<html> <p> 404 is even <p> HELLO is upper</html>