Shell常用命令与脚本实例

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
#!/bin/sh
   
echo "Hello shell"
   
# ----------------------字符串---------------------#
   
readonly URL="定义一个常量:www.baidu.com"
   
your_name="jack"
echo $your_name
echo ${your_name}
   
   
for file in `ls ~/Desktop`; do
    echo "${file}"
done
   
echo $URL
   
your_name1='单引号字符串内部不能有变量,只能固定输出'
your_name2="单引号字符串可以有变量${URL},和转义符\"Hi,转义\""
echo $your_name1
echo $your_name2
   
echo "字符串长度:${#your_name}"
echo "子字符串,从1下标开始读3个字符:${your_name:1:3}"
echo `gexpr index "$your_name1" 固定` #语法错误
echo "使用#号可以截取指定字符(或者子字符串)右边的所有字符, *表示跨过左侧任意个字符:${your_name1#*固定}"
echo "使用%号可以截取指定字符(或者子字符串)左边的所有字符, *表示跨过右侧任意个字符:${your_name1%固定*}"
   
#字符串转数组
string="hello,shell,split,test"
#将,替换为空格
array=(${string//,/ })
  
#字符串包含判断
#字符串是否符合正则表达式?
if [[ ${1} == *\.podspec || ${1} == *\.pbxproj || ${1} == *\.plist || ${1} == *\.sh ]];
#字符串包含:父字符串$filterList 是否包含子字符串$item
if [[ $filterList =~ $item ]]
   
# ----------------------数组---------------------#
  
cities=("北京" "上海" "深圳" "杭州")
echo ${cities[1]}
  
echo ${cities[@]} # @:获取数组中所有的元素
echo ${!cities[@]} # ![@]:获取数组中所有的元素的key键,数组可以放[key:value]对
echo "数组的长度:${#cities[@]}"
  
# 数组包含判断
# 数组包含:数组$"{filterList[@]}" 是否包含字符串"$item"
if [[ "${filterList[@]}" =~ "$item" ]]
# 数组不包含?
if [[ ! "${filterList[@]}" =~ "$item" ]]
  
# 数组添加元素
# 添加方式 语法 可添加多个元素 下标必须连续 添加后下标改变 可能覆盖原有元素
# 直接下标添加 cities[index]=value 否 否 否 是
# 数组长度添加 cities[${#cities[@]}]=valuecities[${#cities[*]}]=value 否 是 否 是
# 重新创建数组 cities=("${cities[@]}" value1 ... valueN) 是 否 是 否
# 赋值运算符+= cities+=(value1 ... valueN) 是 是 是 否
:<<EOF
多行注释: 定义一个函数EOF,但是没有地方调用,达到注释的效果
EOF
  
# ----------------------传递参数---------------------#
  
:<<EOF
$0: 执行文件名
$1: 第一个参数
$2: 第一个参数 . .
EOF
  
echo "执行文件的名称为:$0,传参个数为:$#, 参数值为:$1,$2"
  
# ----------------------运算符执行---------------------#
  
需要获取命令结果返回值的使用下面2种方式
纯命令用``或$()执行 `xcodebuild -list -project aaa.xcodeproj`
带参数用$()执行 $(ls $name)
  
不需要获取命令结果返回值的,直接写命令即可
xcodebuild -list -project aaa.xcodeproj
  
# ----------------------函数---------------------#
  
1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。
return 后跟数值n(0-255)
3、函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数,超过10个用${11}
  
funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
     echo "第十个参数为 $10 !"
     echo "第十个参数为 ${10} !"
     echo "第十一个参数为 ${11} !"
     echo "参数总数有 $# 个!"
     echo "作为一个字符串输出所有参数 $* !"
}
  
funWithParam 1 2 3 4 5 6 7 8 9 34 73
结果:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
  
# ----------------------逻辑运算---------------------#
  
单中括号[],双中括号[[]],小括号(())的区别?
if [[ $a > $b ]] 双中括号支持正则表达式
if [ $a > $b ] 单中括号不支持正则表达式
if (( a > b )) 小括号不用使用$做取值了
  
  
判断:大于,小于,等于,不等于。
在比较时,数字和字符串可以使用不同的比较符号
比较数字 (numberic):-ne
比较字符 (string):!=
多条件使用|| 或者 &&
  
1.如果a>ba<c
if [[ $a > $b ]] && [[ $a < $c ]]
或者
if [ $a -gt $b -a $a -lt $c ]
  
if (( a > b ));
then
...
else
# 如果else里没有处理语句,则else不能写
fi
   
if [ $subCmd == $subCmdValue1 ]; then
fi
if [ ${projName} != "Pods" ]; then
fi
   
判断:非空判断 不为空
if空判断
if [ ! -n "$a" ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi
  
if [ ! $a ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi
  
# ----------------------文件目录---------------------#
  
shell 目录,文件判断
-f "file" : 判断file是否是文件;
-d "file" : 判断file是否是目录(文件夹)。
:<<EOF
xargs 将标准输入作为下一条命令的参数 $
echo "hello world" | xargs echo hello world
上面的代码将管道左侧的标准输出,转为命令行参数hello world,传给第二个echo命令。
EOF
  
 # ----------------------循环遍历---------------------#
  
 sortSchemeNames=(aaa bbb ccc)
 projInfo=`xcodebuild -list -project aa.xcodeproj`
 #目标字符串projInfo中,#*中间间隔任意个字符串直到查到“Schemes:”字符串,返回其右侧的部分
 tragetSchemes=${projInfo#*Schemes:}
 for ((i=0; i<${#schemeNames[@]}; i++)); do
    scheme=schemeNames[i]
    # 父字符串$tragetSchemes 是否包含子字符串$scheme
    if [[ $tragetSchemes =~ $scheme ]] then
        echo "------------第${i}个库构建开始:${scheme}"
        echo "++++++++++++第${i}个库构建结束:${scheme} \n"
    fi
 done
  
 for scheme in ${sortSchemeNames[@]}; do
    if [[ $tragetSchemes =~ $scheme ]] then
        echo "----------> build 开始:${scheme}"
        echo "<---------- build 结束:${scheme} \n"
    fi
 done
  
 # ----------------------路径截取---------------------#
  
 :<<EOF
  
 shell之文件路径截取 file=/dir1/dir2/dir3/my.file.txt
 我们可以用${ }分别替换获得不同的值:
  
 ${file#*/}:拿掉第一条/及其左边的字串:dir1/dir2/dir3/my.file.txt
 ${file##*/}:拿掉最后一条/及其左边的字串:my.file.txt
 ${file#*.}:拿掉第一个.及其左边的字串:file.txt
 ${file##*.}:拿掉最后一个.及其左边的字串:txt
 ${file%/*}:拿掉最后条/及其右边的字串:/dir1/dir2/dir3
 ${file%%/*}:拿掉第一条/及其右边的字串:(空值)
 ${file%.*}:拿掉最后一个.及其右边的字串:/dir1/dir2/dir3/my.file
 ${file%%.*}:拿掉第一个.及其右边的字串:/dir1/dir2/dir3/my
  
 引用地址:http://www.jb51.net/article/94355.htm
  
 EOF
  
 # ----------------------数学运算---------------------#
整数运算使用:(())
小数运算使用:bc
另外:expr(可用于整数运算,也可以处理字符串。比较麻烦)
  
  
语法格式为:((表达式))
表达式可以只有一个,也可以有多个。如果是多个表达式,那么多个表达式之间以逗号,分隔。它们以最后一个表达式的值作为整个 (( )) 命令的执行结果。可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
变量赋值: a=$((10+66) b=$((a-15))
逻辑运算: ((a>7 && b==c))
多表达式: ((a=3+5, b=a+10))
在 (( )) 中使用变量无需加上$前缀,(( )) 会自动解析变量名
  
  
bc Linux 下的一个计算器程序,可以处理整数和小数。Shell 本身只支持整数运算,想计算小数就得使用 bc 这个外部的计算器。
Linux bc 命令的语法格式为:
command "表达式" | bc
  
i=10
echo $i
j=3;
echo $j
  
m=`expr $i / $j`
echo $m
  
n=`echo "scale=9; $i / $j" | bc`
echo $n
scale是指定精度,而且只有在除法的时候才有生效,其他都是安装原来都有几位就输出几位;bc支持除了位操作的所有运算。
  
  
expr 是一款表达式计算工具,可用于整数运算,也可以处理字符串
Shell expr 命令的语法格式为:
$(expr variable + variable) 或者 `expr variable + variable`
表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2
  
i=10
echo $i
  
i=`expr $i + 10` #20
echo $i
  
  
# 加减乘除运算
# 乘法
r=`expr 4 \* 5`
r=$(( 4 * 5 ))
r=$[ 4 * 5 ]
echo $r
   
# 除法
r=`expr 40 / 5`
r=$(( 40 / 5 ))
r=$[ 40 / 5 ]
echo $r
   
# 减法
r=`expr 40 - 5`
r=$(( 40 - 5 ))
r=$[ 40 - 5 ]
echo $r
   
# 求余数
r=$[ 100 % 43 ]
echo $r
   
# 乘幂 (如 2 3 次方)
r=$(( 2 ** 3 ))
r=$[ 2 ** 3 ]
echo $r
 
 # ----------------------多条命令一起执行---------------------#
 
“;”隔开,多条指令无论成败,都会执行
cd /home/PyTest/src; python suning.py
 
&&”隔开,多条指令前面的成功了后面才执行
 
“||”隔开,或,多条指令前面的执行失败,后面才执行
 
“|”隔开,管道符,多条指令无论成败,都会执行

 

脚本案例

批量编译项目Target依赖的所有子Schemes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 产物默认目录下~/Library/Developer/Xcode/DerivedData/*
# -destination generic/platform=iOS \
# -destination generic/platform=iphonesimulator\
  
plateformDevice='generic/platform=iOS'
plateformSim='generic/platform=iphonesimulator'
  
# 1.获取工程下所有的schemes, 遍历构建所有子项目
# 假设脚本在工程的父级目录
projectName="aa.xcodeproj"
projectPath=$(find . -name $projectName)
projectPath=${projectPath%/*}
cd $projectPath
  
projInfo=$(xcodebuild -list -project $projectName)
targetSchemes=${projInfo#*Schemes:}
  
for ((i=0; i<${#sortSchemeNames[@]}; i++)); do
    scheme=${sortSchemeNames[i]}
    if [[ $targetSchemes =~ $scheme ]]
    then
        echo "------------构建开始:${scheme}"
        xcodebuild \
        -destination ${plateformDevice} \
        -workspace ${param1}.xcworkspace \
        -scheme ${scheme} \
        -configuration 'Debug'
        echo "++++++++++++构建结束:${scheme} \n"
    fi
done

 

真机,模拟器分别归档,并打.xcframework包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 真机,模拟器分别归档,并打.xcframework包
# 假设脚本在工程的当前目录
# 执行shell命令,查询当前目录下所有的*.xcodeproj文件
projPaths=$(find . -name *.xcodeproj)
projPath0=${projPaths[0]} # 获取第0个路径
projName=${projPath0##*/} # 获取xxx.xcproj工程名
onlyName=${projName%.*}   # 获取纯净的xxx工程名
  
  
xcodebuild archive \
    -scheme ${onlyName} \
    -sdk iphonesimulator \
    -archivePath "archives/ios_sim.xcarchive" \
    BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
    SKIP_INSTALL=NO
  
  
  
xcodebuild archive \
    -scheme ${onlyName} \
    -sdk iphoneos \
    -archivePath "archives/ios_device.xcarchive" \
    BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
    SKIP_INSTALL=NO
  
  
  
xcodebuild -create-xcframework \
    -framework archives/ios_device.xcarchive/Products/Library/Frameworks/${onlyName}.framework \
    -framework archives/ios_sim.xcarchive/Products/Library/Frameworks/${onlyName}.framework \
    -output build/${onlyName}.xcframework

 

批量查询与批量替换脚本例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/bin/sh
 
filterList=("Pods" "libs" "Scripts" "Makefile" "Podfile" "Podfile.lock" "readme.md" "LEGAL.md" "Assets.xcassets" "xcshareddata" "xcuserdata" "build" "Images.xcassets" "Resources" "Products")
#filterFileList=(*.podspec)
 
# 如果没有输入cp参数,提示输入cp参数
paramNum=$#
subCmd=$1
param1=$2
param2=$3
readonly location=`pwd`
tempPath=""
subCmdValue1="s" #search
subCmdValue2="r" #replace
 
searchTotalCount=0
 
 
 
# ------------------search 查询-------------------
 
 
function checkFileAndDir() {
    searchPath=`pwd`
 
    # -iname:忽略大小写;-name:区分大小写;
    find ${searchPath} -iname $1
     
    echo "查询根目录:${searchPath}"
    items=`ls`
    #字符串转数组,将\n替换为空格
#    items=(${items//\n/ })
    echo $items
    index=0
    for item in `ls`; do
        index=`expr $index + 1`
        echo "\n++++++++开始查询第:${index}个项目,项目名称:${item}  ++++++++\n"
        searchOneDir $item
    done
}
         
 
function searchOneDir(){
    if [ -f ${1} ]; then
     
        if [[ ${1} == *\.podspec || ${1} == *\.pbxproj || ${1} == *\.plist || ${1} == *\.sh ]]; then
            return
        fi
         
#        echo "查询 ${1}"
        res=$(sed -n "/${param1}/Ip" ${1}) #I:取消大小写
#        res=$(sed -n "/${param1}/p" ${1})
        # 非空判断
        if [ -n "$res" ]; then
            searchTotalCount=`expr $searchTotalCount + 1`
            echo "\n递归目录------结果个数:${searchTotalCount} --------:$1 ;"
            echo $res
        fi
         
    elif [ -d ${1} ];then
        #sed -i "" "s/aaa/bbb/g" grep -rl aaa ./
        #grep -rl: l列出文件内容符合条件的文件名, r递归查询
        #$(grep -rl ${param1} ./ | xargs sed -n "/${param1}/Ip")
         
        if [[ ! "${filterList[@]}" =~ "${1}" ]]
        then
            items=$(ls $1)
    #        echo "递归目录------结果个数:${searchTotalCount}--------:$1 ;"
            for item in ${items[@]}; do
    #        for ((i=0; i<${#items[@]}; i++)); do
    #            item=${items[i]}
 
                # [[ $filterList =~ $item ]]字符串包含:父字符串$tragetSchemes 是否包含子字符串$scheme ?
                # [[ "${filterList[@]}" =~ "$item" ]]数组包含:数组$"{filterList[@]}" 是否包含字符串"$item" ?
                # [[ ! "${filterList[@]}" =~ "$item" ]]数组不包含?
 
                if [[ ! "${filterList[@]}" =~ "$item" ]]
                then
    #                echo "进入:$item"
                    searchOneDir "$1/$item"
                fi
             done
        fi
    fi
    return 0;
}
 
 
# ------------------replace 替换-------------------
 
function scannerOneDir(){
    echo "${1}"
    if [ -f ${1} ]
    then
#        if [[ ${1} == *\.podspec || ${1} == *\.sh ]]; then
#            return
#        fi
         
        echo "替换 ${1}"
        sed -i "" "s/${param1}/${param2}/g" ${1}
        echo "替换成功"
    elif [ -d ${1} ]
    then
        #sed -i "" "s/aaa/bbb/g" grep -rl aaa ./
        $(grep -rl ${param1} ./ | xargs sed -i "" "s/${param1}/${param2}/g")
    fi
    return 0;
}
 
function handle() {
    if [ $subCmd == $subCmdValue1 ]; then
       searchOneDir $1;
    else
       scannerOneDir $1;
    fi
}
 
function handleDir() {
    # 进入到目标目录里,进行替换
    if [[ ! "${filterList[@]}" =~ "$1" ]]
    then
        if [[ ${1} == *\.podspec || ${1} == *\.sh ]]; then
            echo "匹配失败:${1}"
        else
            echo "匹配成功:${1}"
            handle ${1};
        fi
    else
        echo "匹配失败:${1}"
    fi
}
  
function scanDir(){
 
    res=`find . -name *.xcodeproj`
    echo $res
    if [[ ! ${res} ]]
    then
        # 扫描的是一个普通文件夹
        for item in `ls`; do
            handleDir ${item};
        done
    else
        # 扫描的是一个xcode项目父文件夹
        for path in ${res[@]}; do
            pathT=${path%.*}
            tempPath=${pathT%/*}
            projName=${pathT##*/}
            if [ ${projName} != "Pods" ]
            then
                echo "------进入项目根目录:${tempPath}, 入参:${param1}, ${param2}"
                cd ${tempPath}
                echo "projName: ${projName}"
                for item in `ls`; do
                    handleDir ${item};
                done
 
                cd ${location}
                echo "++++++退回Ant目录:${location}\n"
            fi
        done
    fi
    return 0;
}
 
 
 
# <<的用法:
# 当shell看到<<的时候,它就会知道下一个词是一个分界符。
# 在该分界符以后的内容都被当作输入,直到shell又看到该分界符(位于单独的一行)。
# 这个分界符可以是你所定义的任何字符串。
 
# EOF与<<结合:
# 通常将EOF与<<结合使用,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主调Shell
 
# EOF特殊用法:
#EOF是(END Of File)的缩写,表示自定义终止符。既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d 就代表EOF。
#EOF一般会配合cat能够多行文本输出。
#其用法如下:
#<<EOF        #开始
#....         #输入内容
#EOF          #结束
 
#熟悉几个特殊符号:
#<:输入重定向
#>:输出重定向
#>>:输出重定向,进行追加,不会覆盖之前内容
#<<:标准输入来自命令行的一对分隔号的中间内容
 
# :<<COMMENTBLOCK
# shell脚本代码段
# COMMENTBLOCK
# 用来注释整段脚本代码。 :是shell中的空语句。
 
 
:<<EOF
shell 目录,文件判断
-f "file"   :  判断file是否是文件;
-d "file"  :  判断file是否是目录(文件夹)。
EOF
 
:<<EOF
xargs 将标准输入作为下一条命令的参数
$ echo "hello world" | xargs echo
hello world
上面的代码将管道左侧的标准输入,转为命令行参数hello world,传给第二个echo命令。
EOF
 
 
if [ $paramNum -lt 2 ]
then
   echo "请输入查询的字符串与要替换的新字符串"
else
    if [ $subCmd == $subCmdValue1 ]; then
        param1=$2
        param2=$3
        echo "开始查询:${param1}"
        checkFileAndDir ${param1}
    elif [ $subCmd == $subCmdValue2 ]; then
        param1=$2
        param2=$3
        echo "查询的字符串:${param1},要替换的新字符串:${param2}"
        scanDir
    else
        param1=$1
        param2=$2
        echo "查询的字符串:${param1},要替换的新字符串:${param2}"
        scanDir
    fi
     
fi

 

 

 

posted @   滴水微澜  阅读(108)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示