shell

2021/7/26 7:37:51

本文主要是介绍shell,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

source filename 与 sh filename 及./filename执行脚本的区别

  1. 当shell脚本具有可执行权限时,用sh filename./filename执行脚本是没有区别得。./filename是因为当前目录没有在PATH中,所有”.”是用来表示当前目录的。
  2. sh filename 重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell新建的、改变的变量不会被带回父shell,除非使用export。
  3. source filename:这个命令其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。

单引号和双引号和反引号``

单引号和双引号用于变量值出现空格时将字符用引号括起来。 二者的主要区别在于,

被单引号括起来的字符都是普通字符,就算特殊字符也不再有特殊含义;
被双引号括起来的字符中,"$"、"“和反引号是拥有特殊含义的,”$"代表引用变量的值,而反引号代表引用命令。
反引号
如果需要调用命令的输出,或把命令的输出赋予变量,则命令必须使用反引号包含,这条命令才会执行,反引号的作用和 $(命令) 是一样的。命令如下:

if 条件判断

注意事项:
[ $yn = “y” ] 位置的空格,和其他语言相差巨大,如果没有空格就会报错

#!/bin/bash
echo "please input y or n"
read yn

if [ $yn = "y" ]; then
	echo "yes"
else
	echo "no"
fi


# 判断A中是否包含B字符串。注意空格,否则语法错误。
A="helloworld"
B="low"
if [[ $A == *$B* ]]
then
    echo "包含"
else
    echo "不包含"
fi

find查找文件

# find本身默认是递归查找
find ./ -type f # 查找当前目录的所有文件,包括子目录里的文件,但是目录不算

find ./ -type f -name "test*" # 查找文件名test开头的文件,f 所有文件,-name 按照名字查找

find结合xargs

# 查找所有图片并复制到指定文件夹,
find  ./ -name "*.pgm" |cp `xargs` ./picture

#下面会删除picture这个文件夹的
rm -rf ./picture/ && mkdir picture && find  ./output/ -name "*.pgm" |cp `xargs` ./picture

grep 分离想要的和不想要的

例子

grep -n "echo" copymodel.sh  #在指定的文件下查找想要的内容
grep -rn "echo" ./			#可以是文件夹,文件夹必须加上-r表示递归,否则报错。
grep -rvn "echo" ./			#-v表示不想要echo,只要没有这个字符串都显示出来。

查找指定字符的下一行行 -A

adb shell dumpsys media.camera | grep -A 1 "android.sensor.frameDuration"

# man grep  看到 -A -B -C 就知道了

与操作
grep同时匹配多个关键字,同时匹配str1、str2和str3
grep ‘str1’ filename | grep ‘str2’ | grep ‘str3’
1
或操作
grep匹配任意关键字
grep -E ‘str1|str2|str3’ filename
1
egrep实现
egrep ‘str1|str2|str3’ filename
1
awk实现
awk ‘/str1|str2/str3/’ filename
1
其他操作
grep -i pattern filename #不区分大小写地搜索。默认情况区分大小写。
grep -l pattern filename #只列出匹配的文件名。
grep -L pattern filename #列出不匹配的文件名。
grep -w pattern filename #只匹配整个单词,而不是字符串的一部分(如匹配‘magic’,而不是‘magical’)。

sed 擅长过滤一下在做其他处理

其他的处理:比如打印、替换,删除等

sed -n '/echo/p' test.sh  
# echo过滤的内容,p是打印的意思。-n:取消默认输出,如果没有-n它会先把文件内容打印出来,在把 echo 打印出来。
# 一般来讲需要加上-n



sed -n '/echo/d' test.sh   # d删除的意思

#替换
#s表示字符串查找并替换,g表示全局范围,还可以替换第几列可以选择。#是分隔符可以用/或者@都可以。
sed  "s#ab#12#g" test.sh  # 将ab替换为12,注意单引号和双引号的区别



sed  "s#ab#$PATH#g" test.sh #替换为环境变量的内容,但是没有真正的替换,先看一下替换后的效果,只是输出返回值,没有赋值
sed -i  "s#ab#$PATH#g" test.sh #-i是真正意义上的替换,


awk

    用途:以列为单位将一行数据分隔成数个“字段”来处理

    awk ‘条件1{动作1} 条件2{动作2} ...’ filename

echo 追加文件内容

清空文件添加内容。

echo "# abc" >test.sh  # 小心:这个会先清空文件在添加内容

追加文件内容

echo "# abc" >> test.sh 

管道和重定向

重定向概念:

标准输入是我们的键盘,标准输出为命令行界面,如果我们想将标准输出改了,不输出到命令行界面了,而是输出到文件,那么这个动作就叫做重定向,意思重新改变输出数据的流向,就是重定向.不能重定向标准错误信息.因为错误的命令不可能被执行的,所以想想也知道.但是可以设置的,也可以将错误信息重定向到文件,日志文件很有用,
在这里插入图片描述

在这里插入图片描述

重定向标准输入

原来我们的标准输入是键盘,现在我们可以改变这个输入,将键盘改变为文件.比如下面这个命令,首先认清什么是标准输入,grep 不是输入,"zjw"也不是输入,而是要查找的关键字,后面的路径文件内容才是标准输入呢.

grep "zjw" < /etc/passwd
grep "zjw"  /etc/passwd

管道

在这里插入图片描述

前面的输出就是后面的输入,所以有必要清楚什么是输入,比如

ls -al | grep "test"

ls -al 输出我们知道,然后将这个输出,当成文本内容,传给了后面的输入,后面的输入就不用在写了.
在这里插入图片描述

grep "关键字" [标准输入,文本内容,或者文件都可以]
如果不写后面的输入,那么命令行就像scanf函数一样卡在那里,等待用户的输入,这个输入就是键盘输入
#查找并替换
find ./ -type f -name "test*"|xargs sed "s/aaa/bbb/g"

下面这个例子:
-user 是参数,按照用户名查找,2> 重定向标准错误,null 像一个垃圾桶,丢弃掉,应该是有这个文件,

find / -user "zjw" 2> /dev/null | grep Video

下面这个用法:没见过。

 echo "ls; exit"|adb shell

xargs用法

下面这两个例子作用不一样,区别很大,

find ./ -name "exampl*" |xargs  grep "Name"
find ./ -name "exampl*" | grep "Name"

解释:
find 是查找文件的,不查找文件内部的内容的. 他的结果,我们知道比如
./Python-RVO2-master/examples 将这个作为文本内容,传给grep

而xargs 将这个文件内容作为参数传给grep ,所以结果完全不一样.

进程相关的

ps -el  # 查看全部进程
ps 
pstree  # 进程树
kill 

shell脚本

这个文档比较好
http://c.biancheng.net/view/810.html

自定义变量

这些变量由用户定义。shell脚本允许我们在脚本中设置和使用自己的变量。设置变量允许您临时存储数据并在整个脚本中使用它,使得shell脚本更像一个真正的计算机程序。
用户变量区分大小写,因此变量Var1与变量var1不同。这个小规则经常让新手脚本程序员陷入困境。

使用等号将值分配给用户变量。变量,等号和值(新手的另一个麻烦点)之间不能有空格。以下是为用户变量赋值的几个示例:

a=1   # 注意之间不允许有空格,否则会报错,新手都会入这个坑。
echo $a

shell脚本自动确定用于变量值的数据类型。shell脚本中定义的变量在shell脚本的整个生命周期中保持其值,但在shell脚本完成时删除。

就像系统变量一样,用户变量可以使用美元符号来引用;如果不适用美元符号,系统将他看出字符串了。

value1=10
value2=$value1     # 注意 不能写成value2=value1   [本人批注]

反引号

#testing=`date`  # 这里 date 是一个命令,可以在terminal中输入,就会出现日期
testing=$(date) # 也可以这么写,
echo "date&time:"$testing

总结:

脚本中我们想要显示原来的$,需要在其前面添加反斜杠;因为脚本在引号内看到$,它就会假定您正在引用一个变量。

我么在定义变量的时候:等号和值之间不能有空格。

当引用一个变量值时使用$,但当引用变量来为其赋值时,不要使用$,否则shell会将变量名称解释为普通文本字符串。
将命令行赋值给变量:使用`(反引号字符)或者使用$()来包围命令。

如`命令`或者$(命令)。

定义数组

#!/bin/sh

#==定义数组===============================================

# 在 Shell 中,用括号( )来表示数组,数组元素之间用空格来分隔。由此,定义数组的一般形式为:
nums=(29 100 13 8 91 44)# 注意,赋值号=两边不能有空格,必须紧挨着数组名和数组元素。

# Shell 是弱类型的,它并不要求所有数组元素的类型必须相同,例如:
arr=(20 56 "http://c.biancheng.net/shell/")

# Shell 数组的长度不是固定的,定义之后还可以增加元素。例如,对于上面的 nums 数组,它的长度是 6,使用下面的代码会在最后增加一个元素,使其长度扩展到 7:
nums[6]=88

# 此外,你也无需逐个元素地给数组赋值,下面的代码就是只给特定元素赋值:
ages=([3]=24 [5]=19 [10]=12)
#以上代码就只给第 3、5、10 个元素赋值,所以数组长度是 3。

数组元素的的获取

#!/bin/bash

nums=(29 100 13 8 91 44)
echo ${nums[@]}  #输出所有数组元素
nums[10]=66  #给第10个元素赋值(此时会增加数组长度)
echo ${nums[*]}  #输出所有数组元素
echo ${nums[4]}  #输出第4个元素,索引从0开始
echo $array[0] #也可以这样使用

获取数组的长度

echo ${#array[@]}
echo ${#array[*]}

shell 命令的特殊符号

$0
当前脚本的文件名,带有绝对路径的文件名


$n
传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。


$#
传递给脚本或函数的参数个数。


$*
传递给脚本或函数的所有参数。

$@
传递给脚本或函数的所有参数。
  $* 和 $@ 的区别
  $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号" “包含时,都以”$1" “$2"…"$n” 的形式输出所有参数,被双引号" “包含时,”$*" 会将所有的参数作为一个整体;"@" 会将各个参数分开,以换行形式输出所有参数。


$?
上个命令的退出状态,或函数的返回值。


$$
当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID

Shell 函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

shell中函数的定义格式如下:

[ function ] funname [()]

{

    action;

    [return int;]

}
说明:

1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255
下面的例子定义了一个函数并进行调用:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

demoFun(){
    echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"

for循环

#/bin/sh

#============================语法1,有点像Python
#!/bin/bash
#for a in {1..10}
#for a in 1 2 3
for a in "abc" "cde" bbb   # bbb 被当成字符串了。
#for   变量    in   {起始值..终止值}  #这里面的起始值和终止值必须是纯数字,不能是$a,即不能是变量的值
#for   变量    in     `命令`
do
  echo $a
#        mkdir /datas/aaa$a
#        cd /datas/aaa$a
#        for b in {1..10}
#        do
#                mkdir bbb$b
#        done
done



#============================语法2,有点像C语言
#for   ((初始值;循环控制;变量变化))
#
#do
#
#        循环主体
#
#done

for (( i = 0; i < 10; i++ )); do
    echo $i
done

read

Read可以带有-a, -d, -e, -n, -p, -r, -t, 和 -s八个选项。

-a :将内容读入到数值中

echo -n "Input muliple values into an array:"
read -a array   # 输入必须以空格为分界符
echo "get ${#array[@]} values in array"  # 获取数组长度

adb shell settings put system screen_off_timeout 600000000 #=这个代码看不懂,是系统手机设置,有什么用?

从百度中找到了,我理解是10分钟后手机进入休眠模式。用手机试一试就知道了。

#获取屏幕休眠时间

adb shell settings get system screen_off_timeout

15000

#更改休眠时间,10分钟

C:\Users\Administrator>adb shell settings put system screen_off_timeout 600000 # 单位毫秒

3 存入一个后缀名为.cvmat文件中,目前这个文件是什么还不清楚。还有很多,有输入有输出,都是什么?

拓展:

#获取亮度是否为自动获取

C:\Users\Administrator>adb shell settings get system screen_brightness_mode

#获取当前亮度值

C:\Users\Administrator>adb shell settings get system screen_brightness

#更改亮度值(亮度值在0—255之间)

C:\Users\Administrator>adb shell settings put system screen_brightness 150

#获取日期时间选项中通过网络获取时间的状态,1为允许、0为不允许

adb shell settings get global auto_time

#更改该状态,从1改为0

C:\Users\Administrator>adb shell settings put global auto_time 0

以及获取、修改wifi状态(wifi_on)、飞行模式(airlpane_mode_on)等,这里也是appium中getNetworkConnection获得设备网络状态的方法。

字符串拼接

logfile=$1
#logfile="./log/test_performance_64bit_mode_0x2203_core7_20190909131036.log"

clResult="./performence/cl_result_${logfile}.csv"
a="aaa"${logfile}

monkey测试截取某两行的字符串

  1. 如果你只想看文件的前100行,可以使用head命令,如

    head -100  filename
    
  2. 如果你想查看文件的后100行,可以使用tail命令,如:

    tail -100  filename 或 tail -n 100  filename
    
  3. 查看文件中间一段,你可以使用sed命令,如:

    sed -n '100,200p' filename 
    

    这样你就可以只查看文件的第100行到第200行。

截取的文件可以用重定向输入到新的文件中:

head -100  filename >a.txt
sed -n '4405725,4442615p' logcat_s400.txt > w22.1_400.log
sed -n '523013,646601p' ./s415/...   > w22.2_415.log

函数

作用:一般用于shell内局部变量的定义,多使用在函数内部

关于局部变量和全局变量:
(1)shell 脚本中定义的变量是global的,作用域从被定义的地方开始,一直到shell结束或者被显示删除的地方为止。
(2)shell函数定义的变量也是global的,其作用域从 函数被调用执行变量的地方 开始,到shell或结束或者显示删除为止。函数定义的变量可以是local的,其作用域局限于函数内部。但是函数的参数是local的。
(3)如果局部变量和全局变量名字相同,那么在这个函数内部,会使用局部变量。

输出带有颜色

https://www.cnblogs.com/cangqinglang/p/9837126.html

格式:
echo -e "\033[字背景颜色;字体颜色m 字符串 \033[0m"  或者
printf "\033[字背景颜色;字体颜色m 字符串 \033[0m"  或者
echo -e "\033[字背景颜色;字体颜色m;ascii码m 字符串 \033[0m 字符串(can null) \n"

例子:带有颜色和背景颜色
echo -e "\033[43;35m david use echo say Hello World \033[0m \n" 
printf "\033[44;36m david use printf say Hello World \033[0m \n" 
echo -e "\033[47;30;5m david use echo say \033[0m Hello World \n"

字体闪烁--牛逼
echo -e "\033[47;30;5m david use echo say \033[0m Hello World \n" 

定义一个函数,使用函数进行输出。

REDCOLOR='\e[1;31m'                                     # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
GREENCOLOR='\e[1;32m'                                   # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
YELLOWCOLOR='\e[1;33m'                                  # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
BLUECOLOR='\e[1;34m'                                    # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
PURPLECOLOR='\e[1;35m'                                  # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
CYANCOLOR='\e[1;36m'                                    # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
NOCOLOR='\e[0m' 

# 使用案例:colorizeEcho $YELLOWCOLOR "Remove existing CrashDump folder on SD Card"
function colorizeEcho () # 两个参数
{
    if [ -n "$JENKINS_BUILD_URL" ]; then                                            # Do not use color if run as a jenkins job.
        echo "$2"
        else
        printf $1
        echo "$2"
        printf $NOCOLOR
    fi
}
# 

字符串处理

获取文件名

path=$1
files=$(ls $path)
files=$(find ./ -name "*.mp4") # 这个方法比较好。将所有文件及子文件夹下的mp4 视频,拿出来带有路径,在处理

for filename in $files
do
 echo $filename >> filename.txt
done

字符串的拼接

在脚本语言中,字符串的拼接(也称字符串连接或者字符串合并)往往都非常简单,例如:

  • 在 PHP 中,使用.即可连接两个字符串;
  • 在 JavaScript 中,使用+即可将两个字符串合并为一个。

然而,在 Shell 中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接,非常简单粗暴。请看下面的例子:

#!/bin/bash

name="Shell"
url="http://c.biancheng.net/shell/"

str1=$name$url  #中间不能有空格
str2="$name $url"  #如果被双引号包围,那么中间可以有空格
str3=$name": "$url  #中间可以出现别的字符串
str4="$name: $url"  #这样写也可以
str5="${name}Script: ${url}index.html"  #这个时候需要给变量名加上大括号

echo $str1
echo $str2
echo $str3
echo $str4
echo $str5

删除字符串

#!/bin/bash

name="Shell"

#删除指定个数字符串
echo ${name:3}   #从0开始算,第3个到最后。 输出:ll
echo ${name:0-2:3}   #从右面第二个开始。 输出:ll

#删除左边字符串
echo ${name#*e}  #删除从左面数,第一e及e左面的操作符。 #和*是运算符。 输出:ll
echo ${name#*e}  #删除从右面数,第一e及e左面的操作符。 #和*是运算符。 输出:ll


# 删除右面字符串
echo ${name%e*} #从右面第一个e开始,搜索关键字 是e,e及右侧的字符串被删除。
echo ${name%%e*} #从左面第一个e开始,搜索关键字 是e

案例:

将aaa文件夹里面的所有文件名保存数组,然后下面的for循环针对每一个文件处理。

设置了颜色处理

#!/bin/bash

REDCOLOR='\e[1;31m'                                     # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
GREENCOLOR='\e[1;32m'                                   # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
YELLOWCOLOR='\e[1;33m'                                  # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
BLUECOLOR='\e[1;34m'                                    # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
PURPLECOLOR='\e[1;35m'                                  # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
CYANCOLOR='\e[1;36m'                                    # CONTROL CODE TO CHANGE COLOR OF TERMINAL TEXT
NOCOLOR='\e[0m' 

# 使用案例:colorizeEcho $YELLOWCOLOR "Remove existing CrashDump folder on SD Card"
function colorizeEcho () # 两个参数
{
    if [ -n "$JENKINS_BUILD_URL" ]; then                                            # Do not use color if run as a jenkins job.
        echo "$2"
        else
        printf $1
        echo "$2"
        printf $NOCOLOR
    fi
}
# 

# files=$(ls aaa)  # 将aaa文件夹里面的所有文件名保存数组,然后下面的for循环针对每一个文件处理。注意是不带路径的文件名
files=$(find ./ -name "*.mp4") # 这个方法比较好。将所有文件及子文件夹下的mp4 视频,拿出来带有路径,在处理
for filename in $files #这里自带文件路径了。
do
 echo "$filename"
 head=${filename%.*} # 删除从右侧数,第一个点,及点。
 txtName="$head.txt" #将head保留的左侧字符,加上.txt

# 处理文件
# mediainfo "./aaa/$filename" > $txtName
mediainfo $filename > $txtName
 #http://blog.chinaunix.net/uid-10062010-id-5751344.html # 该软件的命令使用

 colorizeEcho $YELLOWCOLOR "process <$filename> success to <$txtName> !"
 
done

一次杀死所有寻找出来的线程

ps -ef | grep /bin/bash | awk '{print $2;}' | xargs kill -s 9


这篇关于shell的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程