• Chapter 6 Shell Logic and Arithmetic


    1.1 Doing Arithmetic in Your Shell Script

    Use $(()) or let for integer arithmetic expressions

    1. [maxwell@MaxwellDBA test]$ COUNT=$((COUNT + 5 + MAX * 2))
    2. [maxwell@MaxwellDBA test]$ let COUNT+=5+MAX*2

     These assignment operators are also available with $(()) provided they occur inside the double parentheses.

    1.2 Braching on Conditions

    The if statement in bash is similar in appearance to that in other programming languages:

    1. if [ $# -lt 3 ]
    2. then
    3. printf "%b" "Error. Not enough arguments.\n"
    4. printf "%b" "usage: myscript file1 op file2\n"
    5. exit 1
    6. fi
    7. # or alternatively:
    8. if (( $# < 3 ))
    9. then
    10. printf "%b" "Error. Not enough arguments.\n"
    11. printf "%b" "usage: myscript file1 op file2\n"
    12. exit 1
    13. fi
    14. # a full-blown if with an elif and an else clause:
    15. if (( $# < 3 ))
    16. then
    17. printf "%b" "Error.Not enough arguments.\n"
    18. printf "%b" "usage: myscript file1 op file2\n"
    19. exit1
    20. elif (( $# > 3 ))
    21. then
    22. printf "%b" "Error. Too many arguments.\n"
    23. printf "%b" "usage: myscript file1 op file2\n"
    24. exit2
    25. else
    26. printf "%b" "Argument count correct. Proceeding...\n"
    27. fi
    1. [maxwell@MaxwellDBA test]$ cat trythis.sh
    2. if ls;pwd;cd $1;
    3. then
    4. echo success;
    5. else
    6. echo failed;
    7. fi
    8. pwd
    9. [maxwell@MaxwellDBA test]$ bash ./trythis.sh /tmp
    10. another.file chmod_all2.sh embedded_documentation func_choose_man1.sh nohup.out sample tricky.sh
    11. a.out chmod_all.sh ext.sh func_choose.sh 'Oh the Waste' select_dir.sh trythis.sh
    12. asdfwednnrw2rs2esff.txt cong.txt file.txt lines one.file simplest.sh use_up_option.sh
    13. check_arg_count.sh def.conf func_choice1.sh more.txt quoted.sh simpls.sh zebra.list
    14. check_unset_parms.sh donors.sh func_choose.html myscript.sh readability.sh suffixer.sh
    15. /home/maxwell/shelllearning/test
    16. success
    17. /tmp
    18. [maxwell@MaxwellDBA test]$

    1.3 Testing for File Characteristics

    Use the various file characteristic tests in the test command as part of your if statements.

    1. [maxwell@MaxwellDBA test]$ cat checkfile.sh
    2. #!/usr/bin/env bash
    3. # cookbook filename: checkfile
    4. #
    5. DIRPLACE=/tmp
    6. INFILE=/home/maxwell/shelllearning/test/amazing.data
    7. OUTFILE=/home/maxwell/shelllearning/test/more.results
    8. if [ -d "$DIRPLACE" ]
    9. then
    10. cd $DIRPLACE
    11. if [ -e "$INFILE" ]
    12. then
    13. if [ -w "$OUTFILE" ]
    14. then
    15. doscience < "$INFILE" >> "$OUTFILE"
    16. else
    17. echo "can not write to $OUTFILE"
    18. fi
    19. else
    20. echo "can not read from $INFILE"
    21. fi
    22. else
    23. echo "can not cd into $DIRPLACE"
    24. fi
    25. [maxwell@MaxwellDBA test]$

    Three of them are tested using binary operators,each taking two filenames:

     

    1.4 Testing for More Than One Thing

    Use the operators for logical AND(-a)  and OR(-o) to combine more than one test in an expression.

    1. if [ -r $FILE -a -w $FILE ]
    2. # Will test to see that the file is both readable and writable.

    1.5 Testing for String Characteristics

    Using the single bracket if statements.

    1. [maxwell@MaxwellDBA test]$ cat checkstr.sh
    2. #!/usr/bin/env bash
    3. #cookbook filename: checkstr
    4. #
    5. # if statement
    6. # test a string to see if it has any length
    7. #
    8. # use the command line argument
    9. VAR="$1"
    10. #
    11. if [ "$VAR" ]
    12. then
    13. echo has text
    14. else
    15. echo zero length
    16. fi
    17. #
    18. if [ -z "$VAR" ]
    19. then
    20. echo zero length
    21. else
    22. echo has text
    23. fi
    24. [maxwell@MaxwellDBA test]$

    1.6 Testing for Equal

    The type of comparison you need determines which operator you should use.

    Use the -eq operator for numeric comparisons

     The equality primary = (or ==) for string comparisons.

    1. [maxwell@MaxwellDBA test]$ ls -ltr strvsnum.sh
    2. -rw-rw-r-- 1 maxwell maxwell 323 Jul 26 14:46 strvsnum.sh
    3. [maxwell@MaxwellDBA test]$ cat strvsnum.sh
    4. #!/usr/bin/env bash
    5. #cookbook filename: strvsnum
    6. #
    7. # the old string vs. numeric comparison dilemma
    8. #
    9. VAR1=" 05 "
    10. VAR2="5"
    11. printf "%s" "do they -eq as equal? "
    12. if [ "$VAR1" -eq "$VAR2" ]
    13. then
    14. echo YES
    15. else
    16. echo NO
    17. fi
    18. printf "%s" "do they = as equal? "
    19. if [ "$VAR1" = "$VAR2" ]
    20. then
    21. echo YES
    22. else
    23. echo NO
    24. fi
    25. [maxwell@MaxwellDBA test]$ bash strvsnum.sh
    26. do they -eq as equal? YES
    27. do they = as equal? NO
    28. [maxwell@MaxwellDBA test]$

    1.7 Testing with Pattern Matches

    Use the double-bracket compound statement in an if statement to enable shell-style pattern matches on the righthand side of the equals operator:

    if [[ "${MYFILENAME}" == *.jpg ]]

    1.8 Testing with Regular Expressions

    Use the regular expression matching of the =~ operator.Once it has matched the string. the various parts of the pattern are available in the shell variable $BASH_REMATCH.

    1. [maxwell@MaxwellDBA test]$ cat trackmatch.sh
    2. #!/usr/bin/env bash
    3. # cookbook filename: trackmatch.sh
    4. #
    5. for CDTRACK in *
    6. do
    7. if [[ "$CDTRACK" =~ "([[:alpha:][:blank:]]*)-([[:digit:]]*) - (.*)$" ]]
    8. then
    9. echo Track ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
    10. mv "$CDTRACK" "Track${BASH_REMATCH[2]}"
    11. fi
    12. done
    13. [maxwell@MaxwellDBA test]$

    1.9 Changing Behavior with Redirections

    Use the test -t option in an if statement to branch between the two desired behaviors.

    1.10 Looping for a While

    Use the while looping construct for arithmetic conditions:

    1. # for arithmetic conditions:
    2. while (( COUNT < MAX ))
    3. do
    4. some stuff
    5. let COUNT++
    6. done
    7. # for filesystem-related conditions:
    8. while [ -z "$LOCKFILE" ]
    9. do
    10. some things
    11. done
    12. # for reading input
    13. while read lineoftext
    14. do
    15. process $lineoftext
    16. done

    1.11 Looping with a read

    To clean up this directory it would be nice to get rid of all the scratch files.

    1. # Try
    2. svn status mysrc | grep '^?' | cut -c8- | \
    3. while read FN; do echo "$FN"; rm -rf "$FN"; done
    4. # Or:
    5. svn status mysrc | \
    6. while read TAG FN
    7. do
    8. if [[ $TAG == \? ]]
    9. then
    10. echo $FN
    11. rm -rf "$FN"
    12. fi
    13. done

    1.12 Loop with a Count

    Use a special case of the for syntax,one that looks a lot like C language, but with double parentheses:

    1. [maxwell@MaxwellDBA test]$ for (( i=0 ; i<10 ; i++ )); do echo $i ; done
    2. 0
    3. 1
    4. 2
    5. 3
    6. 4
    7. 5
    8. 6
    9. 7
    10. 8
    11. 9
    12. [maxwell@MaxwellDBA test]$ for i in 1 2 3 4 5 6 7 8 9 10
    13. > do
    14. > echo $i
    15. > done
    16. 1
    17. 2
    18. 3
    19. 4
    20. 5
    21. 6
    22. 7
    23. 8
    24. 9
    25. 10
    26. [maxwell@MaxwellDBA test]$

    The special case of the for loop with C-like syntax is a relatively recent addition to bash. It more general from can be described as :

          for (( expr1 ; expr2 ; expr3 )) ; do list ; done

    1. [maxwell@MaxwellDBA test]$ for (( i=0,j=0; i+j < 10 ; i++, j++ ))
    2. > do
    3. > echo $((i*j))
    4. > done
    5. 0
    6. 1
    7. 4
    8. 9
    9. 16
    10. [maxwell@MaxwellDBA test]$

    1.13 Looping with Floating-Point Values

    The for loop with arithmetic expressions only does integer arithmetic. Use the seq command to generate your floating-point values,

    1. [maxwell@MaxwellDBA test]$ for fp in $(seq 1.0 .01 1.1)
    2. > do
    3. > echo $fp; other stuff too
    4. > done
    5. 1.00
    6. -bash: other: command not found
    7. 1.01
    8. -bash: other: command not found
    9. 1.02
    10. -bash: other: command not found
    11. 1.03
    12. -bash: other: command not found
    13. 1.04
    14. -bash: other: command not found
    15. 1.05
    16. -bash: other: command not found
    17. 1.06
    18. -bash: other: command not found
    19. 1.07
    20. -bash: other: command not found
    21. 1.08
    22. -bash: other: command not found
    23. 1.09
    24. -bash: other: command not found
    25. 1.10
    26. -bash: other: command not found
    27. [maxwell@MaxwellDBA test]$ seq 1.0 .01 1.1 | \
    28. > while read fp
    29. > do
    30. > echo $fp; other stuff too
    31. > done
    32. 1.00
    33. -bash: other: command not found
    34. 1.01
    35. -bash: other: command not found
    36. 1.02
    37. -bash: other: command not found
    38. 1.03
    39. -bash: other: command not found
    40. 1.04
    41. -bash: other: command not found
    42. 1.05
    43. -bash: other: command not found
    44. 1.06
    45. -bash: other: command not found
    46. 1.07
    47. -bash: other: command not found
    48. 1.08
    49. -bash: other: command not found
    50. 1.09
    51. -bash: other: command not found
    52. 1.10
    53. -bash: other: command not found
    54. [maxwell@MaxwellDBA test]$

    1.14 Branching Many Ways

    Use the case statement for a multiway branch:

    1. case $FN in
    2. *.gif) gif2png $FN
    3. ;;
    4. *.png) pngOK $FN
    5. ;;
    6. *.jpg) jpg2gif $FN
    7. ;;
    8. *.tif | *.TIFF) tif2jpg $FN
    9. ;;
    10. *) printf "File not supported: %s" $FN
    11. ;;
    12. esac
    13. # This equivalent to this using if/then/else statements is
    14. if [[ $FN == *.gif ]]
    15. then
    16. gif2png $FN
    17. elif [[$FN == *.png ]]
    18. then
    19. pngOK $FN
    20. elif [[ $FN == *.jpg ]]
    21. then
    22. jpg2gif $FN
    23. elif [[ $FN == *.tif || $FN == *.TIFF ]]
    24. then
    25. tif2jpg $FN
    26. else
    27. printf "File not supported: %s" $FN
    28. fi

    1.15 Parsing Command-Line Arguments

    1. [maxwell@MaxwellDBA test]$ cat dashes
    2. #!/usr/bin/env bash
    3. #cookbook filename:dashes
    4. #
    5. #dashes - print a line of dashes
    6. #
    7. #options: # How many (default 72)
    8. # -c X use char X instead of dashes
    9. #
    10. LEN=72
    11. CHAR='-'
    12. while (( $# > 0 ))
    13. do
    14. case $1 in
    15. [0-9]*) LEN=$1
    16. ;;
    17. -c) shift;
    18. CHAR=${1:--}
    19. ;;
    20. *) printf 'usage: %s [ -c X] [#]\n' $(basename $0) >&2
    21. exit 2
    22. ;;
    23. esac
    24. shift
    25. done
    26. [maxwell@MaxwellDBA test]$ sh dashes -g
    27. usage: dashes [ -c X] [#]
    28. [maxwell@MaxwellDBA test]$ sh /home/maxwell/shelllearning/test/dashes -g
    29. usage: dashes [ -c X] [#]
    30. [maxwell@MaxwellDBA test]$

    1.16 Creating Simple Menus

    Use the select statement to create simple character-based screen menus.

    1. [maxwell@MaxwellDBA test]$ cat dbinit.sh
    2. #!/usr/bin/env bash
    3. #cookbook filename: dbinit.sh
    4. #
    5. DBLIST=$(sh ./listdb | tail + 2)
    6. select DB in $DBLIST
    7. do
    8. echo Initializing database: $DB
    9. mysql -u user -p $DB
    10. done
    11. [maxwell@MaxwellDBA test]$

    1.17 Changing the Prompt on Simple Menus

    The bash enviroment variable $PS3 is the prompt used by select.

    1. #!/usr/bin/env bash
    2. # cookbook filename: dbinit.2
    3. #
    4. DBLIST=$(sh ./listdb | tail +2)
    5. PS3="0 inits >"
    6. select DB in $DBLIST
    7. do
    8. if [ $DB ]
    9. then
    10. echo Initializing database: $DB
    11. PS3="$((i++)) inits >"
    12. mysql -u user -p $DB
    13. fi
    14. done
    15. $

    1.18 Create a Simple RPN Calculator

    Create a calculator using shell arithmetic and RPN notation:

    1. #!/usr/bin/env bash
    2. # cookbook filename: rpncalc
    3. #
    4. # simple RPN command line (integer) calculator
    5. #
    6. # takes the arguments and computes with them
    7. # of the form a b op
    8. # allow the use of x instead of *
    9. #
    10. # error check our argument counts:
    11. if [ \( $# -lt 3 \) -o \( $(($# % 2)) -eq 0 \) ]
    12. then
    13. echo "usage: calc number number op [ number op ] ..."
    14. echo "use x or '*' for multiplication"
    15. exit 1
    16. fi
    17. ANS=$(($1 ${3//x/*} $2))
    18. shift 3
    19. while [ $# -gt 0 ]
    20. do
    21. ANS=$((ANS ${2//x/*} $1))
    22. shift 2
    23. done
    24. echo $ANS

    1.19 Creating a Command-Line Calculator

    1. [maxwell@MaxwellDBA test]$ cat fun_calc.sh
    2. #!/usr/bin/env bash
    3. #
    4. # cookbook filename: func_calc
    5. # Trivial command line calculator
    6. function calc
    7. {
    8. awk "BEGIN {print \"The answer is: \" $* }";
    9. }
    10. [maxwell@MaxwellDBA test]$ sh fun_calc.sh 2 + 3 + 4
    11. [maxwell@MaxwellDBA test]$ sh -x fun_calc.sh 2 + 3 + 4
    12. [maxwell@MaxwellDBA test]$ calc 2 + 3 + 4
    13. -bash: calc: command not found
    14. [maxwell@MaxwellDBA test]$ # cookbook filename: func_calc
    15. [maxwell@MaxwellDBA test]$ # Trivial command line calculator
    16. [maxwell@MaxwellDBA test]$ function calc
    17. > {
    18. > awk "BEGIN {print \"The answer is: \" $* }";
    19. > }
    20. [maxwell@MaxwellDBA test]$ calc 2 + 3 + 4
    21. The answer is: 9
    22. [maxwell@MaxwellDBA test]$ calc 2 + 3 + 4.5
    23. The answer is: 9.5
    24. [maxwell@MaxwellDBA test]$ calc '(2+2-3)*4'
    25. The answer is: 4
    26. [maxwell@MaxwellDBA test]$ calc \(2+2-3\)\*4
    27. The answer is: 4
    28. [maxwell@MaxwellDBA test]$ calc '(2+2-3)*4.5'
    29. The answer is: 4.5
    30. [maxwell@MaxwellDBA test]$
  • 相关阅读:
    【计算机网络】运输层习题(谢希仁)(3)
    NextJS开发:shadcn/ui中Button组件扩展增加图标
    前端刷题记录
    编译deb包之dh_testdir工具集的应用
    ASTM D2863: 塑料最低氧气浓度测试
    Java毕业设计之spring+springmvc实现的小型云盘网盘管理系统-课设大作业
    缓冲区、通道、选择器
    RuntimeError_ Found dtype Long but expected Float
    红队专题-从零开始VC++C/S远程控制软件RAT-MFC-远程控制软件总结
    LRU算法
  • 原文地址:https://blog.csdn.net/u011868279/article/details/125987751