#!/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 “&&”隔开,多条指令前面的成功了后面才执行 “||”隔开,或,多条指令前面的执行失败,后面才执行 “|”隔开,管道符,多条指令无论成败,都会执行
脚本案例
# 产物默认目录下~/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包 # 假设脚本在工程的当前目录 # 执行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
#!/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