辰迅云帮助中心

帮助中心

这篇文章主要为大家展示了“Spring Cloud Alibaba Sidecar多语言微服务异构的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Spring Cloud Alibaba Sidecar多语言微服务异构的示例分析”这篇文章吧。自 Spring Cloud Alibaba 2.1.1 版本后增加了 spring-cloud-alibaba-sidecar 模块作为作为一个代理的服务来间接性的让其他语言可以使用spring cloud alibaba等相关组件。通过与网关的来进行路由的映射,从而可以做到服务的获取,然后可以使用Ribbon间接性调用。如上图, Spring Cloud 应用 请求 sidercar 然后转发给其他语言的模块,优势是对于异构服务代码 零侵入,不需要直接根据 nacos 或其他注册中心 api 注册等使用入门构建其他语言接口服务基于go 写个简单的服务接口http://127.0.0.1:8089/sidecarpackage mainimport ( "encoding/json""fmt""log""net/http")func main() { http.HandleFunc("/sidecar", sidecar) http.HandleFunc("/heath", health) log.Fatal(http.ListenAndServe(":8089", nil)) }func sidecar(w http.ResponseWriter, r *http.Request) { _, _ = fmt.Fprintf(w, "hello spring cloud alibaba sidecar") }func health(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") actuator := make(map[string]string) actuator["status"] = "UP"_ = json.NewEncoder(w).Encode(actuator) }构建 sidercar 应用增加 sidecar 依赖<dependency><groupid>com.alibaba.cloud</groupid><artifactid>spring-cloud-starter-alibaba-sidecar</artifactid><version>2.1.1.RELEASE</version></dependency>配置 application.ymlserver:  port: 8088spring:  cloud:   nacos:    discovery:     server-addr: localhost:8848 application:   name: go-provider# 配置异构服务sidecar:  ip: localhost  port: 8089 health-check-url: http://localhost:8089/health构建 nacos consumer应用application.ymlserver:  port: 8087spring:  cloud:   nacos:    discovery:     server-addr: localhost:8848 application:   name: nacos-consumerconsumer 逻辑@RestController@EnableDiscoveryClient@SpringBootApplicationpublic class NacosConsumerApplication {  public static void main(String[] args) {     SpringApplication.run(NacosConsumerApplication.class, args);   }  @Bean  @LoadBalanced  public RestTemplate restTemplate() {    return new RestTemplate();   }  @Autowired  private RestTemplate restTemplate;  @GetMapping("/test")  public String test() {    return restTemplate.getForObject("http://go-provider/sidecar", String.class);   } }测试使用访问spring cloud consumer 应用curl http://localhost:8087/test输出 go-provider应用hello spring cloud alibaba sidecar以上是“Spring Cloud Alibaba Sidecar多语言微服务异构的示例分析”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注辰迅云行业资讯频道!...

Linux的常用命令总结

2021/8/21 22:37:00

这篇文章主要讲解了“Linux的常用命令总结”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux的常用命令总结”吧!1.ls [选项] [目录名 | 列出相关目录下的所有目录和文件-a  列出包括.a开头的隐藏文件的所有文件-A  通-a,但不列出"."和".."-l  列出文件的详细信息-c  根据ctime排序显示-t  根据文件修改时间排序---color[=WHEN] 用色彩辨别文件类型 WHEN 可以是'never'、'always'或'auto'其中之一   白色:表示普通文件   蓝色:表示目录   绿色:表示可执行文件   红色:表示压缩文件   浅蓝色:链接文件   红色闪烁:表示链接的文件有问题   黄色:表示设备文件   灰色:表示其它文件2.mv [选项] 源文件或目录 目录或多个源文件 | 移动或重命名文件-b  覆盖前做备份-f  如存在不询问而强制覆盖-i  如存在则询问是否覆盖-u  较新才覆盖-t  将多个源文件移动到统一目录下,目录参数在前,文件参数在后eg:   mv a /tmp/ 将文件a移动到 /tmp目录下   mv a b 将a命名为b   mv /home/zenghao test1.txt test2.txt test3.txt3.cp [选项] 源文件或目录 目录或多个源文件 | 将源文件复制至目标文件,或将多个源文件复制至目标目录。-r -R 递归复制该目录及其子目录内容-p  连同档案属性一起复制过去-f  不询问而强制复制-s  生成快捷方式-a  将档案的所有特性都一起复制4.scp [参数] [原路径] [目标路径] | 在Linux服务器之间复制文件和目录-v  详细显示输出的具体情况-r  递归复制整个目录(1) 复制文件:  命令格式:  scp local_file remote_username@remote_ip:remote_folder  或者  scp local_file remote_username@remote_ip:remote_file  或者  scp local_file remote_ip:remote_folder  或者  scp local_file remote_ip:remote_file  第1,2个指定了用户名,命令执行后需要输入用户密码,第1个仅指定了远程的目录,文件名字不变,第2个指定了文件名  第3,4个没有指定用户名,命令执行后需要输入用户名和密码,第3个仅指定了远程的目录,文件名字不变,第4个指定了文件名   (2) 复制目录:  命令格式:  scp -r local_folder remote_username@remote_ip:remote_folder  或者  scp -r local_folder remote_ip:remote_folder  第1个指定了用户名,命令执行后需要输入用户密码;  第2个没有指定用户名,命令执行后需要输入用户名和密码;eg:   从 本地 复制到 远程   scp /home/daisy/full.tar.gz root@172.19.2.75:/home/root    从 远程 复制到 本地   scp root@/172.19.2.75:/home/root/full.tar.gz /home/daisy/full.tar.gz5.rm [选项] 文件 | 删除文件-r  删除文件夹-f  删除不提示-i  删除提示-v  详细显示进行步骤6.touch [选项] 文件 | 创建空文件或更新文件时间-a  只修改存取时间-m  值修改变动时间-r  eg:touch -r a b ,使b的时间和a相同-t  指定特定的时间 eg:touch -t 201211142234.50 log.log    -t time [[CC]YY]MMDDhhmm[.SS],C:年前两位7.pwd 查看当前所在路径8.cd 改变当前目录- :返回上次目录.. :返回上层目录回车  :返回主目录/   :根目录9.mkdir [选项] 目录… | 创建新目录-p  递归创建目录,若父目录不存在则依次创建-m  自定义创建目录的权限  eg:mkdir -m 777 hehe-v  显示创建目录的详细信息10.rmdir 删除空目录-v  显示执行过程-p  若自父母删除后父目录为空则一并删除11.rm [选项] 文件… | 一个或多个文件或目录-f  忽略不存在的文件,不给出提示-i  交互式删除-r  将列出的目录及其子目录递归删除-v  列出详细信息12.echo:显示内容-n  输出后不换行-e  遇到转义字符特殊处理     eg:       echo "hehe"   显示hehe       ehco -e "hehe"    显示he(换行了)he13.cat [选项] [文件]..| 一次显示整个文件或从键盘创建一个文件或将几个文件合并成一个文件-n  编号文件内容再输出-E  在结束行提示$14.tac | 反向显示15.more | 按页查看文章内容,从前向后读取文件,因此在启动时就加载整个文件+n  从第n行开始显示-n  每次查看n行数据+/String    搜寻String字符串位置,从其前两行开始查看-c  清屏再显示-p  换页时清屏16.less | 可前后移动地逐屏查看文章内容,在查看前不会加载整个文件-m  显示类似于more命令的百分比-N  显示行号/   字符串:向下搜索“字符串”的功能?   字符串:向上搜索“字符串”的功能n   重复前一个搜索(与 / 或 ? 有关)N   反向重复前一个搜索(与 / 或 ? 有关)b   向后翻一页d   向后翻半页17.nl [选项]… [文件]… | 将输出内容自动加上行号 -b -b a 不论是否有空行,都列出行号(类似 cat -n) -b t 空行则不列行号(默认) -n 有ln rn rz三个参数,分别为再最左方显示,最右方显示不加0,最右方显示加018.head [参数]… [文件]… | 显示档案开头,默认开头10行-v  显示文件名-c number   显示前number个字符,若number为负数,则显示除最后number个字符的所有内容-number/n (+)number     显示前number行内容,-n number   若number为负数,则显示除最后number行数据的所有内容19.tail [必要参数] [选择参数] [文件] | 显示文件结尾内容-v  显示详细的处理信息-q  不显示处理信息-num/-n (-)num      显示最后num行内容-n +num 从第num行开始显示后面的数据-c  显示最后c个字符-f  循环读取20.vi 编辑文件:w filename 将文章以指定的文件名保存起来  :wq 保存并退出:q! 不保存而强制退出命令行模式功能键1)插入模式   按「i」切换进入插入模式「insert mode」,按"i"进入插入模式后是从光标当前位置开始输入文件;   按「a」进入插入模式后,是从目前光标所在位置的下一个位置开始输入文字;   按「o」进入插入模式后,是插入新的一行,从行首开始输入文字。2)从插入模式切换为命令行模式 按「ESC」键。3)移动光标  vi可以直接用键盘上的光标来上下左右移动,但正规的vi是用小写英文字母「h」、「j」、「k」、「l」,分别控制光标左、下、上、右移一格。  按「ctrl」+「b」:屏幕往"后"移动一页。  按「ctrl」+「f」:屏幕往"前"移动一页。  按「ctrl」+「u」:屏幕往"后"移动半页。  按「ctrl」+「d」:屏幕往"前"移动半页。  按数字「0」:移到文章的开头。  按「G」:移动到文章的最后。  按「$」:移动到光标所在行的"行尾"。  按「^」:移动到光标所在行的"行首"  按「w」:光标跳到下个字的开头  按「e」:光标跳到下个字的字尾  按「b」:光标回到上个字的开头  按「#l」:光标移到该行的第#个位置,如:5l,56l。4)删除文字  「x」:每按一次,删除光标所在位置的"后面"一个字符。  「#x」:例如,「6x」表示删除光标所在位置的"后面"6个字符。  「X」:大写的X,每按一次,删除光标所在位置的"前面"一个字符。  「#X」:例如,「20X」表示删除光标所在位置的"前面"20个字符。  「dd」:删除光标所在行。  「#dd」:从光标所在行开始删除#行5)复制  「yw」:将光标所在之处到字尾的字符复制到缓冲区中。  「#yw」:复制#个字到缓冲区  「yy」:复制光标所在行到缓冲区。  「#yy」:例如,「6yy」表示拷贝从光标所在的该行"往下数"6行文字。  「p」:将缓冲区内的字符贴到光标所在位置。注意:所有与"y"有关的复制命令都必须与"p"配合才能完成复制与粘贴功能。6)替换  「r」:替换光标所在处的字符。  「R」:替换光标所到之处的字符,直到按下「ESC」键为止。7)回复上一次操作  「u」:如果您误执行一个命令,可以马上按下「u」,回到上一个操作。按多次"u"可以执行多次回复。8)更改  「cw」:更改光标所在处的字到字尾处  「c#w」:例如,「c3w」表示更改3个字9)跳至指定的行  「ctrl」+「g」列出光标所在行的行号。  「#G」:例如,「15G」,表示移动光标至文章的第15行行首。21.which 可执行文件名称 | 查看可执行文件的位置,在PATH变量指定的路径中查看系统命令是否存在及其位置22.whereis [-bmsu] [BMS 目录名 -f ] 文件名| 定位可执行文件、源代码文件、帮助文件在文件系统中的位置-b   定位可执行文件。-m   定位帮助文件。-s   定位源代码文件。-u   搜索默认路径下除可执行文件、源代码文件、帮助文件以外的其它文件。-B   指定搜索可执行文件的路径。-M   指定搜索帮助文件的路径。-S   指定搜索源代码文件的路径。23.locate | 通过搜寻数据库快速搜寻档案-r  使用正规运算式做寻找的条件24.find find [PATH] [option] [action] | 在文件树种查找文件,并作出相应的处理选项与参数:1. 与时间有关的选项:共有 -atime, -ctime 与 -mtime 和-amin,-cmin与-mmin,以 -mtime 说明   -mtime n :n 为数字,意义为在 n 天之前的『一天之内』被更动过内容的档案;   -mtime +n :列出在 n 天之前(不含 n 天本身)被更动过内容的档案档名;   -mtime -n :列出在 n 天之内(含 n 天本身)被更动过内容的档案档名。   -newer file :file 为一个存在的档案,列出比 file 还要新的档案档名2. 与使用者或组名有关的参数:   -uid n :n 为数字,这个数字是用户的账号 ID,亦即 UID   -gid n :n 为数字,这个数字是组名的 ID,亦即 GID   -user name :name 为使用者账号名称!例如 dmtsai   -group name:name 为组名,例如 users ;   -nouser :寻找档案的拥有者不存在 /etc/passwd 的人!   -nogroup :寻找档案的拥有群组不存在于 /etc/group 的档案!3. 与档案权限及名称有关的参数:   -name filename:搜寻文件名为 filename 的档案(可使用通配符)   -size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的档案。这个 SIZE 的规格有:       c: 代表 byte       k: 代表 1024bytes。所以,要找比 50KB还要大的档案,就是『 -size +50k 』   -type TYPE :搜寻档案的类型为 TYPE 的,类型主要有:       一般正规档案 (f)       装置档案 (b, c)       目录 (d)       连结档 (l)       socket (s)       FIFO (p)   -perm mode :搜寻档案权限『刚好等于』 mode的档案,这个mode为类似chmod的属性值,举例来说,-rwsr-xr-x 的属性为4755!   -perm -mode :搜寻档案权限『必须要全部囊括 mode 的权限』的档案,举例来说,       我们要搜寻-rwxr--r-- 亦即 0744 的档案,使用-perm -0744,当一个档案的权限为 -rwsr-xr-x ,亦即 4755 时,也会被列出来,因为 -rwsr-xr-x 的属性已经囊括了 -rwxr--r-- 的属性了。   -perm +mode :搜寻档案权限『包含任一 mode 的权限』的档案,举例来       说,我们搜寻-rwxr-xr-x ,亦即 -perm +755 时,但一个文件属性为 -rw-------也会被列出来,因为他有 -rw.... 的属性存在!4. 额外可进行的动作:   -exec command :command 为其他指令,-exec 后面可再接额外的指令来处理搜寻到的结果。   -print :将结果打印到屏幕上,这个动作是预设动作!   eg:       find / -perm +7000 -exec ls -l {} ; ,额外指令以-exec开头,以;结尾{}代替前面找到的内容   | xargs        -i  默认的前面输出用{}代替        eg:           find . -name "*.log" | xargs -i mv {} test425.grep ‘正则表达式’ 文件名 | 用正则表达式搜索文本,并把匹配的行打印出来-c  只输出匹配行的计数。-I  不区分大小写(只适用于单字符)。-l  只显示文件名-v  显示不包含匹配文本的所有行。-n  显示匹配行数据及其行号25.file | 判断文件类型26.gzip [-cdtv#] 檔名 | 压缩、解压缩,源文件都不再存在-d  进行解压缩-c  将压缩的数据输出到屏幕上-v  :显示原档案/压缩文件案的压缩比等信息-#  :压缩等级,-1最快,但压缩比最差,=9最慢,但压缩比最好27.gunzip | 解压缩28.bzip2 | 压缩、解压缩-d  :解压-z  :压缩-k  :保留源文件-c :将压缩的过程产生的数据输出到屏幕上!-v :可以显示出原档案/压缩文件案的压缩比等信息;-# :与 gzip 同样的,都是在计算压缩比的参数, -9 最佳, -1 最快!29.bzcat 读取数据而无需解压30.tar [主选项+辅选项] 文件或者目录 | 多个目录或档案打包、压缩成一个大档案主选项:   -c  建立打包档案,可搭配 -v 来察看过程中被打包的档名(filename)   -t  察看打包档案的内容含有哪些档名,重点在察看『档名』就是了;   -x  解打包或解压缩的功能,可以搭配 -C (大写) 在特定目录解开辅选项:   -j  透过 bzip2 的支持进行压缩/解压缩:此时档名最好为 *.tar.bz2   -z  透过 gzip 的支持进行压缩/解压缩:此时档名最好为 *.tar.gz   -v  在压缩/解压缩的过程中,将正在处理的文件名显示出来!   -f filename -f 后面要立刻接要被处理的档名!   -C 目录   这个选项用在解压缩,若要在特定目录解压缩,可以使用这个选项。   --exclude FILE:在压缩打包过程中忽略某文件 eg: tar --exclude /home/zenghao -zcvf myfile.tar.gz /home/* /etc   -p  保留备份数据的原本权限与属性,常用于备份(-c)重要的配置文件   -P(大写)  保留绝对路径,亦即允许备份数据中含有根目录存在之意;eg:   压 缩:tar -jcvf filename.tar.bz2 要被压缩的档案或目录名称   查 询:tar -jtvf filename.tar.bz2   解压缩:tar -jxvf filename.tar.bz2 -C 欲解压缩的目录31.exit 退出当前shell 32.logout 退出登录shell 33.shutdown -h now34.users 显示当前登录系统地用户35.who 登录在本机的用户与来源-H或--heading  显示各栏位的标题信息列。36.w 登录在本机的用户及其运行的程序-s  使用简洁格式列表,不显示用户登入时间,终端机阶段作业和程序所耗费的CPU时间。-h  不显示各栏位的标题信息列。37.write 给当前联机的用户发消息38.wall 给所有登录再本机的用户发消息39.last 查看用户的登陆日志40.lastlog 查看每个用户最后的登陆时间41.finger [选项] [使用者] [用户@主机] | 查看用户信息-s 显示用户的注册名、实际姓名、终端名称、写状态、停滞时间、登录时间等信息-l 除了用-s选项显示的信息外,还显示用户主目录、登录shell、邮件状态等信息,以及用户主目录下的.plan、.project和.forward文件的内容。-p 除了不显示.plan文件和.project文件以外,与-l选项相同42.hostname 查看主机名43.alias ii = “ls -l” | 添加别名44.unalias ii | 清除别名45.useradd [-u UID] [-g 初始群组] [-G 次要群组] [-c 说明栏] [-d 家目录绝对路径] [-s shell] 使用者账号名 | 新增用户-M  不建立用户家目录!(系统账号默认值)-m  建立用户家目录!(一般账号默认值)-r  建立一个系统的账号,这个账号的 UID 会有限制 -e  账号失效日期,格式为『YYYY-MM-DD』-D  查看useradd的各项默认值46.passwd | 修改密码-l  使密码失效-u  与-l相对,用户解锁-S  列出登陆用户passwd文件内的相关参数-n  后面接天数,shadow 的第 4 字段,多久不可修改密码天数-x  后面接天数,shadow 的第 5 字段,多久内必须要更动密码-w  后面接天数,shadow 的第 6 字段,密码过期前的警告天数-i  后面接『日期』,shadow 的第 7 字段,密码失效日期使用管道刘设置密码:echo "zeng" | passwd --stdin zenghao47.userdel 删除用户-r  用户文件一并删除48.chage [-ldEImMW] 账号名 | 修改用户密码的相关属性-l  列出该账号的详细密码参数;-d  后面接日期,修改 shadow 第三字段(最近一次更改密码的日期),格式YYYY-MM-DD-E  后面接日期,修改 shadow 第八字段(账号失效日),格式 YYYY-MM-DD-I  后面接天数,修改 shadow 第七字段(密码失效日期)-m  后面接天数,修改 shadow 第四字段(密码最短保留天数)-M  后面接天数,修改 shadow 第五字段(密码多久需要进行变更)-W  后面接天数,修改 shadow 第六字段(密码过期前警告日期)49.usermod [-cdegGlsuLU] username | 修改用户的相关属性-c  后面接账号的说明,即 /etc/passwd 第五栏的说明栏,可以加入一些账号的说明。-d  后面接账号的家目录,即修改 /etc/passwd 的第六栏;-e  后面接日期,格式是 YYYY-MM-DD 也就是在 /etc/shadow 内的第八个字段数据啦!-f  后面接天数为 shadow 的第七字段。-g  后面接初始群组,修改 /etc/passwd 的第四个字段,亦即是GID的字段!-G  后面接次要群组,修改这个使用者能够支持的群组-l  后面接账号名称。亦即是修改账号名称, /etc/passwd 的第一栏!-s  后面接 Shell 的实际档案,例如 /bin/bash 或 /bin/csh 等等。-u  后面接 UID 数字啦!即 /etc/passwd 第三栏的资料;-L  冻结密码-U  解冻密码50.id [username] | 查看用户相关的id信息,还可以用来判断用户是否存在51.groups 查看登陆用户支持的群组, 第一个输出的群组为有效群组52.newgrp 切换有效群组53.groupadd [-g gid] 组名 | 添加组-g  设定添加组的特定组id54.groupmod [-g gid] [-n group_name] 群组名 | 修改组信息-g  修改既有的 GID 数字-n  修改既有的组名55.groupdel [groupname] | 删除群组56.gpasswd | 群组管理员功能root管理员动作:   -gpasswd groupname 设定密码   -gpasswd [-A user1,...] [-M user3,...] groupname       -A  将 groupname 的主控权交由后面的使用者管理(该群组的管理员)       -M  将某些账号加入这个群组当中   -gpasswd [-r] groupname       -r  将 groupname 的密码移除群组管理员动作:   - gpasswd [-ad] user groupname        -a  将某位使用者加入到 groupname 这个群组当中       -d  将某位使用者移除出 groupname 这个群组当中57.chfn修改个人信息58.mount [-t vfstype] [-o options] device dir-ro 采用只读方式挂接设备-rw 采用读写方式挂接设备eg:mount /home/mydisk.iso /tmp/mnt 通过mnt访问mydisk内的内容59umount 取消挂载60.cut-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。-c :以字符为单位进行分割。-d :自定义分隔符,默认为制表符。-f  :与-d一起使用,指定显示哪个区域。61.sort-n   依照数值的大小排序。-o<输出文件>   将排序后的结果存入指定的文件。-r   以相反的顺序来排序。-t<分隔字符>   指定排序时所用的栏位分隔字符。-k  选择以哪个区间进行排序。62.wc 统计指定文件中的字节数、字数、行数, 并将统计结果显示输出-l filename 报告行数-c filename 报告字节数-m filename 报告字符数-w filename 报告单词数63.uniq 去除文件中相邻的重复行-c或——count:在每列旁边显示该行重复出现的次数;-d或--repeated:仅显示重复出现的行列;-f<栏位>或--skip-fields=<栏位>:忽略比较指定的栏位;-s<字符位置>或--skip-chars=<字符位置>:忽略比较指定的字符;-u或——unique:仅显示出一次的行列;-w<字符位置>或--check-chars=<字符位置>:指定要比较的字符。64.set 显示环境变量和普通变量 65.env 显示环境变量 66.export 把普通变量变成环境变量 67.unset 删除一个环境变量aaa(){} 定义函数68.read-p  接提示字符-t  接等待的秒数69.declare、typeset-i 声明为整数-a 声明为数组-f 声明为函数-r 声明为只读70.ulimit 限制使用者的某些系统资源-f  此 shell 可以建立的最大档案容量 (一般可能设定为 2GB)单位为 Kbytes eg: ulimit -f 1024 限制使用者仅能建立 1MBytes 以下的容量的档案71.df [选项] [文件] | 显示指定磁盘文件的可用空间,如果没有文件名被指定,则所有当前被挂载的文件系统的可用空间将被显示-a  显示全部文件系统-h  文件大小友好显示-l  只显示本地文件系统-i  显示inode信息-T  显示文件系统类型72.du [选项] [文件] | 显示每个文件和目录的磁盘使用空间-h  方便阅读的方式-s  只显示总和的大小73.ln [参数] [源文件或目录] [目标文件或目录] | 某一个文件在另外一个位置建立一个同步的链接-s  建立软连接   -v  显示详细的处理过程74.diff [参数] [文件1或目录1] [文件2或目录2] | 比较单个文件或者目录内容-b  不检查空格字符的不同。-B  不检查空白行。-i  不检查大小写-q  仅显示差异而不显示详细信息eg: diff a b > parch.log 比较两个文件的不同并产生补丁75.date [参数]… [+格式] | 显示或设定系统的日期与时间%H 小时(以00-23来表示)。 %M 分钟(以00-59来表示)。 %P AM或PM。%D 日期(含年月日)%U 该年中的周数。date -s “2015-10-17 01:01:01″ //时间设定date +%Y%m%d         //显示前天年月日date +%Y%m%d --date="+1 day/month/year"  //显示前一天/月/年的日期date +%Y%m%d --date="-1 day/month/year"  //显示后一天/月/年的日期date -d '2 weeks' 2周后的日期76.cal [参数] 月份] [年份] | 查看日历-1  显示当月的月历-3  显示前、当、后一个月的日历-m  显示星期一为一个星期的第一天-s  (默认)星期天为第一天-j  显示当月是一年中的第几天的日历-y  显示当前年份的日历77.ps | 列出当前进程的快照a   显示所有的进程-a  显示同一终端下的所有程序e   显示环境变量f   显示进程间的关系-H  显示树状结构r   显示当前终端的程序T   显示当前终端的所有程序-au 显示更详细的信息-aux    显示所有包含其他使用者的行程 -u  指定用户的所有进程78.top [参数] | 显示当前系统正在执行的进程的相关信息,包括进程ID、内存占用率、CPU占用率等79.kill [参数] [进程号] | 杀死进程80.free [参数] | 显示linux系统中空闲的、已用的物理内存及swap内存,及被内核使用的buffer81.vmstat | 对操作系统的虚拟内存、进程、CPU活动进行监控82.iostat [参数] [时间t] [次数n](每隔t时间刷新一次,最多刷新n次)| 对系统的磁盘操作活动进行监视,汇报磁盘活动统计情况,同时也会汇报出CPU使用情况-p[磁盘] 显示磁盘和分区的情况83.watch [参数] [命令] |重复执行某一命令以观察变化-n  时隔多少秒刷新-d  高亮显示动态变化84.at [参数] [时间] | 在一个指定的时间执行一个指定任务,只能执行一次HH:MM[am|pm] + number [minutes|hours|days|weeks] 强制在某年某月某日的某时刻进行该项任务atq 查看系统未执行的任务atrm n 删除编号为n的任务at -c n 显示编号为n的任务的内容85.crontab | 定时任务调度file    载入crontab-e  编辑某个用户的crontab文件内容-l  显示某个用户的crontab文件内容-r  删除某个用户的crontab文件86.ifconfig [网络设备] [参数] | 查看和配置网络设备87.route | 显示和操作IP路由表88.ping [参数] [主机名或IP地址] | 测试与目标主机的连通性-q  只显示最后的结果89.netstat | 显示与IP、TCP、UDP和ICMP协议相关的统计数据90.telnet [参数] [主机] | 用于远程登录,采用明文传送报文,安全性不好91.rcp [参数] [源文件] [目标文件] | 远程文件拷贝-r  递归复制-p  保留源文件的属性usage: rcp –r remote_hostname:remote_dir local_dir92.wget [参数] [URL地址] | 直接从网络上下载文件-o FILE 把记录写到FILE文件中    eg : wget -O a.txt URLwget --limit-rate=300k URL  限速下载93.awk-F 分隔符  以分隔符分隔内容{}  要执行的脚本内容 eg:cat /etc/passwd |awk  -F ':'  '{print $1""$7}'94.sed 对数据行进行替换、删除、新增、选取等操作a   新增,在新的下一行出现c   取代,取代 n1,n2 之间的行 eg: sed '1,2c Hi' abd   删除i   插入,在新的上一行出现95.paste 合并文件,需确保合并的两文件行数相同-d  指定不同于空格或tab键的域分隔符-s  按行合并,单独一个文件为一行96.su [参数] user | 切换登陆-l  切换时连同环境变量、工作目录一起改变-c command  执行command变回原来的使用者97sudo | 以特定用户的权限执行特定命令-l  列出当前用户可执行的命令-u username#uid 以指定用户执行命令感谢各位的阅读,以上就是“Linux的常用命令总结”的内容了,经过本文的学习后,相信大家对Linux的常用命令总结这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是辰迅云,小编将为大家推送更多相关知识点的文章,欢迎关注!...

这篇文章给大家分享的是有关javascript中Hoisting的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。简介“变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。 实际上变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。声明变量的方法var、let、const 不用以上关键字直接赋值的变量会挂载与windows环境下;let a=9const a=1var a=6c=5声明函数的方法javascript中声明函数的方法有两种:函数声明式和函数表达式。//函数声明function say(){   console.log('hello')  }//函数表达式var say=function (){   console.log('hello')  }提升的好处JavaScript 在执行任何代码段之前,将函数声明放入内存中的优点之一是,这允许你可以在在声明该函数之前使用一个函数。/*** 正确的方式:先声明函数,再调用函数 (最佳实践)*/function catName(name) {   console.log("我的猫名叫 " + name); } catName("Tigger");/*以上代码的执行结果是: "我的猫名叫 Tigger"*//*** 不推荐的方式:先调用函数,再声明函数 */catName("Chloe");function catName(name) {   console.log("我的猫名叫 " + name); }/*代码执行的结果是: "我的猫名叫 Chloe"*/提升规则var 声明的变量,提升时只声明,不赋值,默认为undefined;不用关键字直接赋值的变量不存在提升(demo1)函数提升会连带函数体一起提升,不执行;(deom2)预解析的顺序是从上到下;(demo4)函数的优先级高于变量,函数声明提前到当前作用域最顶端;(deom3)变量重名,提升时不会重复定义;在执行阶段后面赋值的会覆盖上面的赋值;(demo4)函数重名,提升时后面的会覆盖前面;(demo5)函数和变量重名,提升函数,不会重复定义,变量不会覆盖函数;在执行阶段后面赋值的会覆盖上面的赋值;(demo8)用函数表达式声明函数,会按照声明变量规则进行提升;(deom6)函数执行时,函数内部的变量声明和函数声明也按照以上规则进行提升;(deom7)let、const不存在提升;(demo9、demo10)/**demo1**/console.log('a=',a) //a=undefinedconsole.log('b=',b) // Uncaught ReferenceError: b is not definedvar a=1b=6/**deom2**/console.log('a=',a) // a=function a() {console.log("func a()")}function a() {console.log("func a()") }/**deom3**/console.log('a=',a) // a=function a() {console.log("fun a")}var a=3var a=4function a(){console.log("fun a") }var a=5var a=6console.log("a=",a) // a=6 /**deom4**/console.log('a=',a) // a=undefinedvar a =2console.log('a=',a) //var a =3var a =4console.log('a=',a) // a=4console.log('b=',b) //b= undefinedvar b='b1'/**deom5**/console.log('a=',a) // a=function a() {console.log("a2")}function a(){console.log("a1") }function a(){console.log("a2") }console.log('a=',a) // a=function a() {console.log("a2")}/**deom6**/console.log('a=',a) // a=undefinedvar a=function(){console.log('a1')}var a=3var a=4var a=5console.log(a)var a=function(){console.log('a2')}console.log('a=',a) // a= ƒ (){console.log('a2')}/**deom7**/console.log('b=',b)var a=3function b(i){   console.log('a=',a)   var a=4  function a(){     console.log('fun a')   }   console.log('a=',a) } b()/**demo8**/console.log('a=',a) //a= function a(){ console.log('fun a')}var a=2function a(){   console.log('fun a') }console.log('a=',a) // a=2var a=3var a=4var a=5console.log('a=',a) // a=5/**demo9**/console.log('a=',a) //Uncaught ReferenceError: a is not definedlet a=4/****/<!--demo10-->console.log('b=',b) // Uncaught ReferenceError: b is not definedconst b=5感谢各位的阅读!关于“javascript中Hoisting的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!...

这篇文章将为大家详细讲解有关如何使用函数式编程对JavaScript进行断舍离,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。关于DHTMLDHTML是Dynamic HTML的简称,就是动态的html(标准通用标记语言下的一个应用),是相对传统的静态的html而言的一种制作网页的概念。所谓动态HTML(Dynamic HTML,简称DHTML),其实并不是一门新的语言,它只是HTML、CSS和客户端脚本的一种集成,即一个页面中包括html+css+javascript(或其它客户端脚本),其中css和客户端脚本是直接在页面上写而不是链接上相关文件。在那个时候,JavaScript的演化很慢,主要应用在表单验证。因此,不像今天这么火爆,并没有引起太多的关注。可以说只是一个锦上添花的附加物,你需要确保在浏览器禁用JavaScript之后,你的应用依然可以正常使用。再往后,框架一个接着一个出现:jQuery,Knockout, Angular, React, Vue, 等等。同样,JavaScript也在加速演化。我们才使用ES6不久,现在人们几乎已经跳过ES7,开始讨论ES8了。并且,我们有很多替代品,比如TypeScript,CoffeScript,ClojureScript, ELM,等等。我们已经被太多的框架和语言所淹没,很难去跟踪和掌握所有的语言和框架。错误路线当JavaScript逐渐成熟,面向对象编程(OOP)的概念也渗入进来,而且我曾经很喜欢。我开始尝试所有不同的方法来创建类,我最终也可以正确的使用继承。我对自己说:JavaScript开始真的像一个语言了!但是,直到多年以后我发现OOP是JavaScript引入的最糟糕的一个设计!我尝试将我对C#的理解带入到JavaScript中去。一开始充满期待,但是后来发现真的太复杂,太烧脑了。这主要是因为JavaScript的原型继承和C#不一样,我已经习惯于每天编写类似于console.log(this)这样飘逸的代码。但是现在呢?如果我一不小心没按照规则来,那将会给我带来噩梦。私有方法和私有值必须要在名字前面加上下划线,甚至必须用闭包来保证私有性。因此,不仅OOP导致了很多问题,同时也由于添加OOP带来了很多新的问题。函数式编程一开始我并不理解。我可以阅读并理解这些用函数式编写的代码,但是不知道为什么!最终,我强迫我自己去学习它。函数式语言给了我一个全新的视角,让我从一个完全不同的方式去看待编程。一开始会感到不自然,需要时间去适应。所有的定义都是基于函数,值不可更改,无状态。我用函数式的思维去解决问题。因为不熟悉,我花了更长的时间去学习。渐渐地,我熟练掌握了使用函数式的方法去编程。并且,我也知道所有代码这样编写的内在含义。我的代码更加简洁了,而且容易复用。渐渐的,我以前使用的那些语言特性从代码中消失了,我的代码看上去完像是用另一个语言编写。我还在用JavaScript吗?1. 不再使用var我用const替代了var。通过函数式的设计,我的函数都是纯(pure)的。不会再去对一个变量进行值的变更操作,同样也是为了确保不会对其操作。我会检查代码确保每一个var,甚至let,所有声明都使用const。2. 没有for循环在学习程序语言的时候,我们一开始就会学到for循环。但是自从学习了函数式编程,我将for循环都改成了使用filter, map和reduce来实现。对于那些需要一些额外计算的需求,我会使用递归或则第三方库比如lazy.js。如今我的代码里面完全没有for循环了,如果你看到了,告诉我我会把它消除。3. if也可以被简化我开始停止在if里面编写大块大块的代码。我将里面的逻辑抽取出来单独放在一个函数中。这样,我们就可以将if用三元算子(a?b:c)来简化。如今我的代码里面几乎没有if语句。为了方便其他开发者理解我的代码,我很少使用它。4. 和switch说拜拜同样,我也不喜欢用switch,而是寻找一个函数式的写法。我也很喜欢用Ramda的cond算子来替代swtich。5. 不在担心this对的,你没有听错!我们也可以完全消除this。函数式的JavaScript可以让你完全抛弃使用烦人的this现在只有数据和函数,甚至数据不过是函数的一种特殊表达形式,你再也不需要this了。我开始将对象理解为函数式语言中状态(state)和函数。我甚至不需要把状态或则函数和对象绑定到一起,就像OOP中那样。面向对象的设计不是必须的现在往回看,我发现面型对象编程带来的复杂度真的是不必要的。我可以使用函数式语言实现同样的功能,完成相同的任务。而且,代码更加轻简,因为不在需要将这些复杂的对象传来传去。只有数据和函数,而且因为函数没有和对象绑定,更加容易复用。我不在需要担心传统的原型继承带来的所有的问题,JavaScript设计的并不好。JavaScript缺乏私有、公有、内部或则被保护这类访问控制器也不再是一个问题。访问控制器是用来解决由于引入面向对象编程而设计的。在函数式的JavaScript中,这些问题不复存在。总结我的代码现在看上去完全不同。它包含了很多纯函数,我将它们做成不同的ES6模块。这些函数可以被使用来构建更加复杂的函数。很大一部分函数都是很简单的一行lambda表达式。现在我看待软件的思维也变了:输入是一个数据流,然后程序作用到该数据流上对数据进行各种操作,然后返回新的数据。函数式设计对程序语言的影响以及无处不在,C#中的LINQ就是一个最佳的例子。同样Java 8也引入了函数式语言的特性。关于“如何使用函数式编程对JavaScript进行断舍离”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。...

小编给大家分享一下基于vue2.0动态组件及render怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!如下所示:<template> <div class="hello"> <h2>{{ msg }}</h2> <h3>这里是Boor</h3> <component v-bind:my-data="items" v-bind:is="currentView">  <!-- 组件在 vm.currentview 变化时改变! --> </component> <a class="explain">直直</a> <button v-on:click="addData">点击</button> </div></template><script> //import $ from '@/assets/scripts/lib/zepto.min' //console.log($); //import Vue from 'vue' function isEmptyObject(e) {  var t;  for (t in e)   return !1;  return !0 }  function objectLength(o) {   var len = 0;   for(var p in o) {    len++;   }   return len;  }  let data ={   c_0:{c:1},   c_1:{c:2},   c_2:{c:3},   c_3:{c:4}  };  let num = 0;  //console.log(objectLength(data)); const MyComponent = {  //template: '<h4 v-for="item in items">{{ item.c}}</h4>', props: ['myData'],  data(){   return{   //items : myData  }  },  render: function (createElement) {   debugger;   let items = this.myData;    //items = JSON.stringify(items);  let num = objectLength(items);  if (!isEmptyObject(items)) {   debugger;   return createElement('div', Array.apply(null, { length: num }).map(function (v,index) {   return createElement('h4', items['c_'+index]['c'].toString())   }))  } else {   return createElement('h2', '没有数据!');  }  }  };  // 注册 //Vue.component('my-component', MyComponent);export default {  name: 'bar',  data () {  return {   msg: 'Bar',   fuck: 'Hello',   items: data,   currentView: MyComponent  }  },  methods:{  addData : function(){   for(let p in data) {    if(p == 'c_'+num) {     data[p] = {'c': num };    } else {     data['c'+num] = {'c': num };    }   }   num++;  }  } };</script><!-- Add "scoped" attribute to limit CSS to this component only --><style scoped>h2, h3 {  font-weight: normal; }ul {  list-style-type: none;  padding: 0; }li {  display: inline-block;  margin: 0 10px; }a {  color: #42b983; }</style>以上是“基于vue2.0动态组件及render怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注辰迅云云资讯频道!...

小编给大家分享一下Scratch3.0如何实现页面初始化并同时加载sb3文件,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!scratch是一种非常合适的培养自己的编程兴趣的方式。通过拖拽的方式,可以实现一些游戏,小程序的开发,就像搭积木一样目标文件地址:src\containers\sb-file-uploader.jsx修改 sb-file-uploader.jsx文件, class SBFileUploader中添加componentDidMount(),代码如下componentDidMount() {      var _this = this; // 作品所在存放地址 var sb3Path = null; /**  * 必须使用 $(window).on("load",function(){});  * 否则页面在未加载完的情况下,有些组件会来不及加载,影响二次文件保存  */ console.log("尚未初始加载Sb3文件"); $(window).on("load",function(){ console.log("即将初始加载Sb3文件"); let reader = new FileReader(); let request = new XMLHttpRequest(); console.log("加载的资源路径", sb3Path); request.open('GET', sb3Path, true); request.responseType = "blob"; request.onload = function() { if(request.status==404){ alert("未找到sb3类型的资源文件"); location.href='/scratch'; } let blobs = request.response reader.readAsArrayBuffer(blobs); reader.onload = () => _this.props.vm.loadProject(reader.result).then(() => { analytics.event({ category: 'project', action: 'Import Project File', nonInteraction: true }); _this.props.onLoadingFinished(_this.props.loadingState); }).catch(error => { log.warn(error); }); } request.send(); }); }目标文件地址:src\components\menu-bar\menu-bar.jsx修改 menu-bar.jsx文件, class MenuBar 中初始SBFileUploader,代码如下// 必须加载这个文件import SBFileUploader from '../../containers/sb-file-uploader.jsx';class MenuBar extends React.Component {         render () {              return (             <Box                 className={classNames(                     this.props.className,                     styles.menuBar,                     {[styles.saveInProgress]: this.props.isUpdating}                 )}             > <SBFileUploader onUpdateProjectTitle={PropTypes.func} /** 初始化加载文件到项目 **/> {(className, renderFileInput, loadProject) => ( <button onClick={loadProject} className={classNames(styles.scratchHide)}></button> )} </SBFileUploader>             </Box>         );     } } export default injectIntl(connect(     mapStateToProps,     mapDispatchToProps )(MenuBar));以上是“Scratch3.0如何实现页面初始化并同时加载sb3文件”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注辰迅云资讯频道!...

如何在Bash中编写函数

2021/8/17 22:08:05

本篇内容主要讲解“如何在Bash中编写函数”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何在Bash中编写函数”吧!通过编写函数来减少代码的冗余和维护。在编程时,实际上是在定义要由计算机执行的过程procedure或例程routine。一个简单的类比是将计算机编程与烤面包进行比较:你一次列出了要组建工作环境的配料,然后列出了烤面包所必须采取的步骤。在编程和烘烤中,必须以不同的间隔重复执行某些步骤。例如,在烤面包中,这可能是酵母培养的过程:STIR=100SNOOZE=86400 function feed_culture {   remove_from(pantry)   add(flour, water)   stir($STIR)   sleep($SNOOZE) }然后,揉面和醒发面团:KNEAD=600SNOOZE=7200 function process_dough {   remove_from(proofing_drawer)   knead($KNEAD)   return_to_drawer($SNOOZE) }在编程中,这些子例程subroutines可以表示为函数function。函数对程序员很重要,因为它们有助于减少代码中的冗余,从而减少了所需的维护量。例如,在以编程方式烤制面包的假想场景中,如果你需要更改面团醒发的用时,只要你之前使用函数,那么你只需更改一次用时,或使用变量(在示例代码中为 SNOOZE)或直接在处理面团的子程序中更改用时。这样可以节省你很多时间,因为你不必通过你的代码库遍历每个可能正在醒发的面团,更不用说担心错过一个。许多 bug 是由未更改的缺失的值或执行不正确的 sed  命令引起的,它们希望捕获所有可能而不必手动寻找。在 Bash 中,无论是在编写的 脚本或在独立的文件中,定义函数和使用它们一样简单。如果将函数保存到独立的文件中。那么可以将它 source 到 脚本中,就像 include C 语言或 C++ 中的库或将模块 import 到 Python 中一样。要创建一个 Bash 函数,请使用关键字 function:function foo {# code here}这是一个如何在函数中使用参数的例子(有些人为设计,因此可能会更简单):#!/usr/bin/env bashARG=$1 function mimic {   if [[ -z $ARG ]]; then    ARG='world'  fi  echo "hello $ARG"}   mimic $ARG结果如下:$ ./mimic hello world $ ./mimic everybody hello everybody请注意脚本的最后一行,它会执行该函数。对于编写脚本的新手来说,这是一个普遍的困惑点:函数不会自动执行。它们作为潜在的例程存在,直到被调用。如果没有调用该函数,那么函数只是被定义,并且永远不会运行。如果你刚接触 Bash,请尝试在包含最后一行的情况下执行示例脚本一次,然后在注释掉最后一行的情况下再次执行示例脚本。使用函数即使对于简单的脚本,函数也是很重要的编程概念。你越适应函数,在面对一个不仅需要声明性的 命令行,还需要更多动态的复杂问题时,你就会越容易。将通用函数保存在单独的文件中还可以节省一些工作,因为它将帮助你建立常用的程序,以便你可以在项目间重用它们。看看你的脚本习惯,看是否适合使用函数。到此,相信大家对“如何在Bash中编写函数”有了更深的了解,不妨来实际操作一番吧!这里是辰迅云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!...

这篇文章给大家分享的是有关Python中可迭代对象、迭代器、For循环工作机制、生成器的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1.iterable iterator区别要了解两者区别,先要了解一下迭代器协议:迭代器协议是指:对象需要提供__next__()方法,它返回迭代中的元素,在没有更多元素后,抛出StopIteration异常,终止迭代。可迭代对象就是:实现了迭代器协议的对象。协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)通过迭代器协议访问对象,因此,for循环并不需要知道对象具体是什么,只需要知道对象能够实现迭代器协议即可。迭代器(iterator)与可迭代对象(iterable)并不是同一个概念。直观上:1.可迭代对象(iterable):凡是具有__iter__的方法的类,都是可迭代的类。可迭代类创建的对象实现了__iter__方法,因此就是可迭代对象。用list、tuple等容器创建的对象,都是可迭代对象。可迭代对象通过__iter__方法返回一个迭代器,然后在内部调用__next__方法进行迭代,最后没有元素时,抛出异常(这个异常python自己会处理,不会让开发者看见)。2.迭代器(iterator):迭代器对象必须同时实现__iter__和__next__方法才是迭代器。对于迭代器来说,__iter__ 返回的是它自身 self,__next__ 则是返回迭代器中的下一个值,最后没有元素时,抛出异常(异常可以被开发者看到)。从上面2点可以看出:1.迭代器一定是可迭代对象,因为它实现了__iter__()方法;2.通过iter()方法(在类的内部就是__iter__)能够使一个可迭代对象返回一个迭代器。3.迭代器的 __iter__ 方法返回的是自身,并不产生新的迭代器对象。而可迭代对象的 __iter__ 方法通常会返回一个新的迭代器对象。第3点性质正是可迭代对象可以重复遍历的原因(每次返回一个独立的迭代器,就可以保证不同的迭代过程不会互相影响);而迭代器由于返回自身,因此只能遍历一次。上面3点可以通过下面的例子看出来:from collections import Iterablefrom collections import Iteratorprint isinstance(iter([1,2]),Iterator)print isinstance(iter([1,2]),Iterable)print isinstance([1,2],Iterator)print isinstance([1,2],Iterable)##resultTrueTrueFalseTrue##id可以查看一个对象在内存中的地址test=[1,2,3] testIter=iter(test)print id(testIter)print id(testIter)print id(iter(test))print id(iter(test))print id(test.__iter__())print id(test.__iter__())##result:可迭代对象每次调用iter方法都会返回一个新的迭代器对象,而迭代器对象调用iter方法返回自身67162576 67162576 67162688 67162632 67162856 671630242.iterable的工作机制拿一个例子看看,首先定义一个有__iter__方法,但是没有next()方法的类 (PS:在python2中是next(),python3是__next__()):from collections import Iterable, Iteratorclass Student(object): def __init__(self,score): self.score=score  def __iter__(self): return iter(self.score)   test= Student([80,90,95])print isinstance(test, Iterable)print isinstance(test, Iterator)for i in test:  print i##resultTrueFalse809095##可重复遍历for i in test:  print i##result809095上面代码的结果印证了定义中提到的:缺少了next()方法,可迭代对象就不是迭代器。此外,注意到:可迭代对象通过__iter__方法每次都返回了一个独立的迭代器,这样就可以保证不同的迭代过程不会互相影响。也就是说,通过iterable可以实现重复遍历,而迭代器是无法重复遍历的!因此,如果想要把可迭代对象转变为迭代器,可以先调用iter()方法返回一个迭代器。然后就可以用next()不断迭代了!print isinstance(iter(test),Iterator) testIter=iter(test)print testIter.next()print testIter.next()print testIter.next()##resultTrue 80 90 95##一旦取完了可迭代对象中所有的元素,再次调用next就会发生异常print testIter.next()##resultStopIteration:3.迭代器Iterator的工作机制看下面这个例子:class Student(object): def __init__(self,score):  self.score=score  def __iter__(self):  return self   def next(self):  if self.score<100:  self.score+=1 return self.score  else: raise StopIteration()   test= Student(90) print isinstance(test, Iterable) print isinstance(test, Iterator) print test.next() print test.next() print test.next()for i in test: print i##resultTrue True919293949596979899100##如果此时再对test这个迭代器调用next方法,就会抛出异常test.next()##resultStopIteration:这个例子印证了定义中的:迭代器对象必须同时实现__iter__和__next__方法才是迭代器。那么,使用迭代器好处在哪呢?Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。一个很常见的应用就是:Python在处理列表的时候,是直接把整个列表读进内存的,当遇到大量样本时的时候会变得很慢。而迭代器的优势在于只把需要的元素读进内存,因此占用内存更少。换句话说,迭代器是一种惰性求值模式,它是有状态的,只有在调用时才返回值,没有调用的时候就等待下一次调用。这样就节省了大量内存空间。这个例子印证了定义中的:迭代器对象必须同时实现__iter__和__next__方法才是迭代器。那么,使用迭代器好处在哪呢?Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。一个很常见的应用就是:Python在处理列表的时候,是直接把整个列表读进内存的,当遇到大量样本时的时候会变得很慢。而迭代器的优势在于只把需要的元素读进内存,因此占用内存更少。换句话说,迭代器是一种惰性求值模式,它是有状态的,只有在调用时才返回值,没有调用的时候就等待下一次调用。这样就节省了大量内存空间。4.for循环的工作机制有了上面2个例子,就可以总结一下在可迭代对象与迭代器中的For循环工作机制了。当对象本身就是迭代器时,For循环工作机制:调用 __iter__方法,返回自身self,也就是返回迭代器。不断地调用迭代器的next()方法,每次按序返回迭代器中的一个值。迭代到最后没有元素时,就抛出异常 StopIteration在可迭代对象中,for循环工作机制:先判断对象是否为可迭代对象(等价于判断有没有__iter__或__getitem__方法),没有的话直接报错,抛出TypeError异常。有的话,调用 __iter__方法,返回一个迭代器。在python内部不断地调用迭代器的__next__方法,每次按序返回迭代器中的一个值。迭代到最后没有元素时,就抛出异常 StopIteration,这个异常 python 自己会处理,不会暴露给开发者。借用网络上的一张图直观理解一下:此外,还要注意,python中的for循环其实兼容了两种机制:如果对象有__iter__会返回一个迭代器。如果对象没有__iter__,但是实现了__getitem__,会改用下标迭代的方式。__getitem__可以帮助一个对象进行取数和切片操作。当for发现没有__iter__但是有__getitem__的时候,会从0开始依次读取相应的下标,直到发生IndexError为止,这是一种旧的迭代协议。iter方法也会处理这种情况,在不存在__iter__的时候,返回一个下标迭代的iterator对象来代替。一个重要的例子是str,字符串就是没有__iter__方法的,但是却依然可以迭代,原因就是其在for循环时调用了__getitem__方法。看一个例子:from collections import Iterable, Iteratorclass Student(object): def __init__(self,score): self.score=score  def __getitem__(self,n): return self.score[n]   test= Student([80,90,95])print isinstance(test, Iterable)print isinstance(test, Iterator)print isinstance(iter(test), Iterable)print isinstance(iter(test), Iterator)for i in test:  print i##resultFalseFalseTrueTrue809095for i in range(0,3):  print test[i]##result809095for i in iter(test):  print i##result809095可以看到,实现了__getitem__方法的对象本身,尽管不是iterable与iterator,仍旧是可以调用for循环的。通过iter方法,返回一个下标迭代的iterator对象。5.generator的原理最后说一下生成器,生成器是一种特殊的迭代器,当然也是可迭代对象。对于生成器,Python会自动实现迭代器协议,以便应用到迭代中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常。创建生成器的方法:将return 改为yield。具体的实现网络上教程很多,不细说了。6.总结到一幅图片很好的描述了本文的所有内容,就拿它作为文末的总结吧!感谢各位的阅读!关于“Python中可迭代对象、迭代器、For循环工作机制、生成器的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!...

这篇文章主要为大家展示了“javascript怎么颠倒元素位置”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“javascript怎么颠倒元素位置”这篇文章吧。首先我们来看一个小例子。<script>var arr = new Array(3);  arr[0] = "one"; arr[1] = "two"; arr[2] = "three";console.log(arr);console.log(arr.reverse());console.log(arr);</script>这个小例子的结果是我们看看这个结果,第一个结果是很正常的,就是我们定义的,没有问题,第二个结果就开始有点意思了,他被反着输出来了,第三个的结果也很有意思,原本以为会按原数组输出,居然没有,看来这个有点东西啊。这个结果里,我们将数组里的元素“["one", "two", "three"]”反着“["three", "two", "one"]”输出了。看来javascript中真的有将元素颠倒位置的方法啊。那我们可需要好好学习这个方法啦。这个方法的名称叫做reverse。reverse()方法用于颠倒数组中元素的顺序。再来看上面这个例子,我们第一次输出arr这个数组的时候,它是按照我们定义的来输出的。然后当我们使用reverse()这个方法之后,再输出arr这个数组,它就会按照我们颠倒数组后元素的顺序来输出。所以我们可以得出一个结论:该方法会改变原来的数组,而不会创建新的数组。现在我们就来学习一下这个方法的语法格式吧,加深一下印象。数组对象.reverse()以上是“javascript怎么颠倒元素位置”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注辰讯云资讯频道!...

网站怎么阻止网络爬虫

2021/8/16 22:30:19

这篇文章主要为大家展示了“网站怎么阻止网络爬虫”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“网站怎么阻止网络爬虫”这篇文章吧。两种主要方法可以阻止爬虫:1.屏蔽它的 IP 地址。收集爬虫的所有 IP (这可能没什么难度),并将它们添加到您的网络服务器、防火墙或任何其他您可能正在使用的软件或服务的黑名单中保护您的网站。有了这种块,爬虫甚至无法开始连接到您的网站,这意味着花费在对抗爬虫上的资源最少。当然可以在应用程序级别执行相同的操作 - 通过分析请求者的 IP 地址并提供错误、空回复或断开连接。但这意味着花费了太多资源(包括您编写逻辑的时间),而不是仅仅使用您的网络服务器的设施。而这种情况一般通过更换代理ip就可以解决掉,更换一个高匿名的代理ip,再次进入网站就不会被屏蔽掉了。2. 屏蔽更高级别的爬虫- 通过分析“用户代理”HTTP 标头,并提供一些 HTTP 错误,例如 503,而不是内容。您也可以直接断开连接,而不是在回复上花费资源。这意味着爬虫不会隐藏其身份,也不会使用某些Web浏览器的用户代理。这也意味着您在接受连接、分析请求和提供回复上花费了相当多的系统资源。一般不会将 robots.txt 称为阻止爬虫的方法,因为想阻止的大多数爬虫无论如何都不尊重 robots.txt。但是,如果您的问题是关于如何指示像 Googlebot 这样礼貌的抓取工具要抓取您网站的哪些部分,那么 robots.txt 是一种组织爬虫的选择。以上是“网站怎么阻止网络爬虫”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注辰迅云资讯频道!...