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 [@]}]= value 或 cities [${# 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 > b 且 a < 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 |
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了