前言
对于经常使用adb的同学,不可避免的一定会这样用adb,比如我们想在手机里执行ps命令,于是在命令行中写下如下代码:
adb shell ps -ef
或者
adb shell "ps -ef"
两种方式都可以,你喜欢用哪个呢?你知道二者有什么区别吗?????
shell中双引号的2个作用
要想知道adb shell ps -ef 与 adb shell "ps -ef"的区别,得先知道双引号""在shell脚本中的作用,双引号的2个重要作用:
1、单词分隔功能失效(空白字符:换行、空格、制表符)
shell默认使用空白字符对单词分隔,此时由于单词分隔功能失效,所以"ps -ef" ,成为一个整体,从参数的角度看,算作1个参数(如果没有双引号,就算2个参数)
2、仍对4种特殊字符解释,其他特殊字符不解释
这四个特殊字符是:命令替换、变量名替换、数字计算、转义字符
命令替换:"$()"
变量名替换:"${}"
整数计算:"$[]"
转义字符:\n
adb命令的角度看:adb收到的参数数量不同
上面已经交代了shell中双引号的作用,这说明adb shell ps -ef和adb shell "ps -ef",参数数量的是不同的
adb命令收到3个参数,分别是shell、ps、-ef,bash解释器通过空白字符,分隔单词,所以是3个参数
adb shell ps -ef
adb命令收到2个参数,由于双引号已经让单词分隔功能失效,所以shell、以及"ps -ef" ,这2个参数传递给adb命令
adb shell "ps -ef"
有重定向时,有无双引号的差别
无双引号
adb shell ps -ef > ./hello.txt
有双引号
adb shell "ps -ef > /sdcard/hello.txt"
他们之间有什么区别呢?我们继续往下看
命令重定向时,命令并不知情重定向的事情
ps命令根本不知道自己的标准输出写到文件中了,它只是认为仍然写入到标准输出中,至于重定向,都是bash解释器作的事情
最大的区别,文件位置的不同
1、重定向到本地主机的文件中
adb shell ps -ef > ./hello.txt
对于adb命令,它只收到3个参数,shell、ps、-ef,至于后面的 > ./hello.txt,不会作为参数传递给命令,而是本地主机的bash解释器自行处理进行重新向的,所以会在本地主机中,而不是手机中,创建一个hello.txt文件,用于插入adb命令返回的标准输出
2、重定向手机文件中
adb shell "ps -ef > /sdcard/hello.txt"
对于adb命令,此时收到2个参数,shell、以及"ps -ef > /sdcard/hello.txt",所以ps命令的标准输出其实是写入到手机的/sdcard/hello.txt文件中,这是由Android上的bash解释器处理的,所以它自然会写入到手机的文件中
管道符,也有不同
无双引号
adb shell ps -ef | grep camera
有双引号
adb shell "ps -ef | grep camera"
最大的区别,执行的是主机的命令、还是手机上的命令,以grep为例
1、执行的是本地主机的grep
adb shell ps -ef | grep camera
bash解释器看到管道符,代表adb命令以及后面的参数就到管道符那里,所以adb收到了3个参数,分别是shell、ps、-ef。 而 | grep camera,则是由bash解释器继续处理,调用本地主机的grep命令,使用grep的标准输入来接收前一个adb命令的标准输出
2、执行的是手机上的grep命令
adb shell "ps -ef | grep camera"
""命令已经让"ps -ef | grep camera"成为一个整体,对于adb,它只收到了2个参数,分别是shell、"ps -ef | grep camera",当传入到手机中,调用的是手机上的grep命令
总结
1、空白字符包括换行符、制表符、空格符
2、shell编程中双引号""的作用要牢记,双引号会让单词分隔功能失效(使用空白字符分隔),再双引号的内部仅支持命令替换、变量名替换、整数计算、转义字符这四种特殊字符的解释,其他字符,bash解释器不再解释,比如 重定向 >,还有管道 |都不会被解释
3、重定向、管道符是bash解释器处理的,对于命令本身,他们只向标准输出写入、标准错误写入、重定向到文件、或者通过管道进入到其他命令的标准输入,命令本身是不知道的
4、理解不同点后,可以避免编写adb命令的一些坑,尤其是使用windows命令行的时候,毕竟windows默认终端上没有grep命令