#!/bin/bash # array-ops.sh: 数组更多有趣的用法. array=( zero one two three four five ) # 元素 0 1 2 3 4 5 echo ${array[0]} # zero echo ${array:0} # zero # 第一个元素的参数扩展, #+ 从位置0开始 (即第一个字符). echo ${array:1} # ero # 第一个元素的参数扩展, #+ 从位置1开始 (即第二个字符). echo "--------------" echo ${#array[0]} # 4 # 数组第一个元素的长度. echo ${#array} # 4 # 数组第一个元素的长度. # (另一种写法) echo ${#array[1]} # 3 # 数组第二个元素的长度. # Bash的数组是0开始索引的. echo ${#array[*]} # 6 # 数组中元素的个数. echo ${#array[@]} # 6 # 数组中元素的个数. echo "--------------" array2=( [0]="first element" [1]="second element" [3]="fourth element" ) echo ${array2[0]} # 第一个元素 echo ${array2[1]} # 第二个元素 echo ${array2[2]} # # 因为初始化时没有指定,因此值为空(null). echo ${array2[3]} # 第四个元素 exit 0 #!/bin/bash # array-strops.sh: 用于数组的字符串操作符. # 由Michael Zick编码. # 已征得作者的同意. # 一般来说,任何类似 ${name ... } 写法的字符串操作符 #+ 都能在一个数组的所有字符串元素中使用 #+ 像${name[@] ... } 或 ${name[*] ...} 的写法. arrayZ=( one two three four five five ) echo # 提取尾部的子串 echo ${arrayZ[@]:0} # one two three four five five # 所有的元素. echo ${arrayZ[@]:1} # two three four five five # 在第一个元素 element[0]后面的所有元素. echo ${arrayZ[@]:1:2} # two three # 只提取在元素 element[0]后面的两个元素. echo "-----------------------" # 子串删除 # 从字符串的前部删除最短的匹配, #+ 匹配字串是一个正则表达式. echo ${arrayZ[@]#f*r} # one two three five five # 匹配表达式作用于数组所有元素. # 匹配了"four"并把它删除. # 字符串前部最长的匹配 echo ${arrayZ[@]##t*e} # one two four five five # 匹配表达式作用于数组所有元素. # 匹配"three"并把它删除. # 字符串尾部的最短匹配 echo ${arrayZ[@]%h*e} # one two t four five five # 匹配表达式作用于数组所有元素. # 匹配"hree"并把它删除. # 字符串尾部的最长匹配 echo ${arrayZ[@]%%t*e} # one two four five five # 匹配表达式作用于数组所有元素. # 匹配"three"并把它删除. echo "-----------------------" # 子串替换 # 第一个匹配的子串会被替换 echo ${arrayZ[@]/fiv/XYZ} # one two three four XYZe XYZe # 匹配表达式作用于数组所有元素. # 所有匹配的子串会被替换 echo ${arrayZ[@]//iv/YY} # one two three four fYYe fYYe # 匹配表达式作用于数组所有元素. # 删除所有的匹配子串 # 没有指定代替字串意味着删除 echo ${arrayZ[@]//fi/} # one two three four ve ve # 匹配表达式作用于数组所有元素. # 替换最前部出现的字串 echo ${arrayZ[@]/#fi/XY} # one two three four XYve XYve # 匹配表达式作用于数组所有元素. # 替换最后部出现的字串 echo ${arrayZ[@]/%ve/ZZ} # one two three four fiZZ fiZZ # 匹配表达式作用于数组所有元素. echo ${arrayZ[@]/%o/XX} # one twXX three four five five # 为什么? echo "-----------------------" # 在从awk(或其他的工具)取得数据之前 -- # 记得: # $( ... ) 是命令替换. # 函数以子进程运行. # 函数将输出打印到标准输出. # 用read来读取函数的标准输出. # name[@]的写法指定了一个"for-each"的操作. newstr() { echo -n "!!!" } echo ${arrayZ[@]/%e/$(newstr)} # on!!! two thre!!! four fiv!!! fiv!!! # Q.E.D: 替换部分的动作实际上是一个'赋值'. # 使用"For-Each"型的 echo ${arrayZ[@]//*/$(newstr optional_arguments)} # 现在Now, 如果if Bash只传递匹配$0的字符串给要调用的函数. . . # echo exit 0 #!/bin/bash # days-between.sh: Number of days between two dates. # Usage: ./days-between.sh [M]M/[D]D/YYYY [M]M/[D]D/YYYY # # Note: Script modified to account for changes in Bash 2.05b #+ that closed the loophole permitting large negative #+ integer return values. ARGS=2 # Two command line parameters expected. E_PARAM_ERR=65 # Param error. REFYR=1600 # Reference year. CENTURY=100 DIY=365 ADJ_DIY=367 # Adjusted for leap year + fraction. MIY=12 DIM=31 LEAPCYCLE=4 MAXRETVAL=255 # Largest permissable #+ positive return value from a function. diff= # Declare global variable for date difference. value= # Declare global variable for absolute value. day= # Declare globals for day, month, year. month= year= Param_Error () # Command line parameters wrong. { echo "Usage: `basename $0` [M]M/[D]D/YYYY [M]M/[D]D/YYYY" echo " (date must be after 1/3/1600)" exit $E_PARAM_ERR } Parse_Date () # Parse date from command line params. { month=${1%%/**} dm=${1%/**} # Day and month. day=${dm#*/} let "year = `basename $1`" # Not a filename, but works just the same. } check_date () # Checks for invalid date(s) passed. { [ "$day" -gt "$DIM" ] || [ "$month" -gt "$MIY" ] || [ "$year" -lt "$REFYR" ] && Param_Error # Exit script on bad value(s). # Uses "or-list / and-list". # # Exercise: Implement more rigorous date checking. } strip_leading_zero () # Better to strip possible leading zero(s) { #+ from day and/or month return ${1#0} #+ since otherwise Bash will interpret them } #+ as octal values (POSIX.2, sect 2.9.2.1). day_index () # Gauss' Formula: { # Days from Jan. 3, 1600 to date passed as param. day=$1 month=$2 year=$3 let "month = $month - 2" if [ "$month" -le 0 ] then let "month += 12" let "year -= 1" fi let "year -= $REFYR" let "indexyr = $year / $CENTURY" let "Days = $DIY*$year + $year/$LEAPCYCLE - $indexyr + $indexyr/$LEAPCYCLE + $ADJ_DIY*$month/$MIY + $day - $DIM" # For an in-depth explanation of this algorithm, see #+ http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm echo $Days } calculate_difference () # Difference between to day indices. { let "diff = $1 - $2" # Global variable. } abs () # Absolute value { # Uses global "value" variable. if [ "$1" -lt 0 ] # If negative then #+ then let "value = 0 - $1" #+ change sign, else #+ else let "value = $1" #+ leave it alone. fi } if [ $# -ne "$ARGS" ] # Require two command line params. then Param_Error fi Parse_Date $1 check_date $day $month $year # See if valid date. strip_leading_zero $day # Remove any leading zeroes day=$? #+ on day and/or month. strip_leading_zero $month month=$? let "date1 = `day_index $day $month $year`" echo $date1 Parse_Date $2 check_date $day $month $year strip_leading_zero $day day=$? strip_leading_zero $month month=$? date2=$(day_index $day $month $year) # Command substitution. echo $date2 calculate_difference $date1 $date2 abs $diff # Make sure it's positive. diff=$value echo $diff exit 0 # Compare this script with #+ the implementation of Gauss' Formula in a C program at: #+ http://buschencrew.hypermart.net/software/datedif #!/bin/bash exec 3<007en exec 4<007cn no=1 while read f1 <&3 && read f2 <&4 do #echo $f1\($f2\) tmpname=${f1}"("${f2}")" #echo $tmpname allnames[$no]=$tmpname let "no+=1" done #let "count=no-1" no=1 for i in * do if ! [ -d $i ] then continue fi pref=${i:0:4} tmpname=${allnames[$no]} newname=$pref$tmpname #echo $newname if ! [ $i = $newname ];then mv -v $i $newname fi let "no+=1" done #!/bin/bash for i in * do if [ ! -d $i ];then continue fi cd $i \rm -v *gif *html *htm *js for j in * do if [ -d $j ] then \rm -rv $j continue fi #找出含有jpg或jpeg的图片 a=`echo $j|grep jpg` xa=`echo $?` b=`echo $j|grep jpeg` xb=`echo $?` if [ $xa -eq 1 ] && [ $xb -eq 1 ] then \rm -v $j continue fi #得到图片的尺寸 sze=`identify $j|awk '{print $3}'` width=${sze%x*} height=${sze#*x} if [ $width -lt 400 ] && [ $height -lt 400 ] then \rm -v $j fi done cd .. done #!/bin/sh # Last modified: 2003年07月05日 星期六 00时09分44秒 [test] SOURCE=$1 TARGET=$2 #CP=./fack_cp CP=cp $CP "$SOURCE" "$TARGET" & CPID=$! isalive(){ out=`ps -p $1 2> /dev/null` return $? } while [ 1 ]; do { SSIZE=`/bin/ls -l $SOURCE | gawk "{print \\\$5}"` if [ -f $TARGET ]; then TSIZE=`/bin/ls -l $TARGET | gawk "{print \\\$5}"` else TSIZE="0" fi PERCENT=`echo "scale=2; $TSIZE/$SSIZE*100" | bc -l` RATE=`echo "scale=0; 63*$PERCENT/100" | bc -l` BLUE="\\033[3;44m" NORMAIL="\\033[0;39m" BAR=$BLUE i=0 while [ $i -le 62 ]; do [ $i = $RATE ] && BAR=$BAR"\\033[7;39m" BAR=$BAR" " let i=$i+1 done BAR=$BAR$NORMAIL echo -en "\r$BAR ${PERCENT}%" if ! isalive "$CPID"; then echo -en "\n"; exit; fi sleep 1 } done #!/bin/bash #eval命令的另一种使用方法 #做算术运算要使用表达式((count=$#))或者let "count=$#", #如果使用count=$#赋值,shell则认为count是字符串 ((count=$#)) cmd=echo while : do cmd="$cmd \$$count" ((count=`expr $count-1`)) if [ $count -eq 0 ] then break fi done eval $cmd #!/bin/bash let allrows=144/16 let allcols=176/16 #echo "allrows="$allrows #echo "allcols="$allcols #echo $# if [ $# -lt 1 ] then echo "Usage xxx row col" elif [ $# -eq 1 ] then let row=$1/$allrows let col=$1%$allcols echo "row="$row echo "col="$col elif [ $# -ge 2 ] then row=$1 col=$2 echo "row="$row echo "col="$col fi let rowS=$row*4+1 let rowE=$rowS+3 let colS1=$col*4+1 let colS2=$col*4+2 let colS3=$col*4+3 let colS4=$col*4+4 #echo "colS1="$colS1 "colS2="$colS2 "colS3"=$colS3 "colS4"=$colS4 #aa="${rowS},${rowE}" #echo $aa #sed -n "$rowS"','"$rowE"'p' mv.txt |awk '{print $colS1 $colS2 $colS3 $colS4}' sed -n "$rowS"','"$rowE"'p' mv.txt |awk -v colS1=$colS1 -v colS2=$colS2 -v colS3=$colS3 -v colS4=$colS4 '{print $colS1 $colS2 $colS3 $colS4}' #!/bin/bash # rnd.sh: 输出一个10进制随机数 # Script by Stephane Chazelas. head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p' # =================================================================== # # 分析 # ---- # head: # -c4 选项将取得前4个字节. # od: # -N4 选项将限制输出为4个字节. # -tu4 选项将使用无符号10进制格式来输出. # sed: # -n 选项, 使用 "s" 命令与 "p" 标志组合的方式, # 将会只输出匹配的行. # 本脚本作者解释 'sed' 命令的行为如下. # head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p' # ----------------------------------> | # 假设一直处理到 "sed"命令时的输出--> | # 为 0000000 1198195154n # sed 命令开始读取字串: 0000000 1198195154n. # 这里它发现一个换行符, #+ 所以 sed 准备处理第一行 (0000000 1198195154). # sed命令开始匹配它的 <range> 和 <action>. 第一个匹配的并且只有这一个匹配的: # range action # 1 s/.* //p # 因为行号在range中, 所以 sed 开始执行 action: #+ 替换掉以空格结束的最长的字符串, 在这行中这个字符串是 # ("0000000 ") ,用空字符串(//)将这个匹配到的字串替换掉, 如果成功, 那就打印出结果 # ("p" 在这里是 "s" 命令的标志, 这与单独的 "p" 命令是不同的). # sed 命令现在开始继续读取输入. (注意在继续之前, #+ continuing, 如果没使用 -n 选项的话, sed 命令将再次 #+ 将这行打印一遍). # 现在, sed 命令读取剩余的字符串, 并且找到文件的结尾. # sed 命令开始处理第2行(这行也被标记为 '$' # 因为这已经是最后一行). # 所以这行没被匹配到 <range> 中, 这样sed命令就结束了. # 这个 sed 命令的简短的解释是: # "在第一行中删除第一个空格左边全部的字符, #+ 然后打印出来." # 一个更好的来达到这个目的的方法是: # sed -e 's/.* //;q' # 这里, <range> 和 <action> 分别是 (也可以写成 # sed -e 's/.* //' -e q): # range action # nothing (matches line) s/.* // # nothing (matches line) q (quit) # 这里, sed 命令只会读取第一行的输入. # 将会执行2个命令, 并且会在退出之前打印出(已经替换过的)这行(因为 "q" action), #+ 因为没使用 "-n" 选项. # =================================================================== # # 也可以使用如下一个更简单的语句来代替: # head -c4 /dev/urandom| od -An -tu4 exit 0