跟着GPT学习shell脚本,学习脚本中的各种符号(一)。

Shell脚本符号深入学习计划

第1周:基本符号和它们的用法
  • 学习目标 :掌握基本的Shell符号,如#, ;, &&, ||
  • 内容
    • #用于注释。
    • ;用于在一行中分隔多个命令。
    • &&||用于连接命令,实现逻辑控制。
第2周:变量和参数扩展
  • 学习目标 :深入理解$符号,包括变量扩展和参数扩展。
  • 内容
    • 变量扩展基础:$VAR${VAR}的区别和用法。
    • 特殊参数扩展:$#, $*, $@, $?, $$
第3周:引号和字符串处理
  • 学习目标 :学习单引号'、双引号"和反引号`````的使用技巧。
  • 内容
    • 单引号和双引号在变量扩展中的区别。
    • 反引号用于命令替换。
第4周:重定向和管道符号
  • 学习目标 :掌握>, >>, <, |等用于I/O重定向和管道的符号。
  • 内容
    • 输入输出重定向:>, >>, <
    • 管道符号|的高级用法。
第5周:文件名扩展和通配符
  • 学习目标 :理解*, ?, []等文件名扩展和通配符的使用。
  • 内容
    • 通配符在文件操作中的应用。
    • 复杂的文件名匹配模式。
第6周:条件测试和表达式
  • 学习目标 :深入学习[ ], [[ ]], (( )){ }的使用。
  • 内容
    • 条件测试[ ][[ ]]的区别。
    • 算术扩展(( ))的应用。
    • 大括号扩展{ }的高级用法。
第7周:脚本调试和错误处理
  • 学习目标 :学习使用set命令和trap进行脚本调试和错误处理。
  • 内容
    • set -x, set -e等选项的使用。
    • 使用trap捕捉和处理信号。
第8周:高级特性探索
  • 学习目标:探索子shell、进程替换等高级Shell特性。
  • 内容
    • 子shell的使用(( ))和场景。
    • 进程替换<()()>的用法。
第9-12周:综合应用和实践
  • 学习目标:综合应用所学的Shell符号,解决实际问题。
  • 内容
    • 结合前面学习的符号,编写综合性脚本。
    • 分析现有脚本,理解符号的应用。
    • 案例研究,提高解决实际问题的能力。

第1周:基本符号和它们的用法

学习目标
  • 掌握基本的Shell符号:#, ;, &&, ||
学习内容
  1. 注释符号 (#)

    • 学习如何使用#来添加注释。
    • 理解注释对提高脚本可读性的重要性。
  2. 命令分隔符 (;)

    • 使用;在一行中分隔多个命令。
    • 比较分隔符与换行符的不同用法。
  3. 逻辑运算符 (&&||)

    • 使用&&在前一个命令成功时执行下一个命令。
    • 使用||在前一个命令失败时执行下一个命令。
    • 组合使用&&||进行更复杂的逻辑控制。
实践任务
  • 任务 :编写一个简短的Shell脚本,其中包含注释,使用;分隔命令,并使用&&||来组合命令。

  • 示例脚本

bash 复制代码
#!/bin/bash

# 检查文件是否存在,如果存在则打印内容
FILE="/path/to/your/file"
[ -f "$FILE" ] && echo "File exists." || echo "File does not exist."

# 使用分号分隔命令
echo "Updating system"; sudo apt update; sudo apt upgrade

第2周:变量和参数扩展

学习目标
  • 深入理解Shell中的变量和参数扩展机制。
学习内容
  1. 基础变量扩展

    • 学习$VAR${VAR}的基本使用,理解它们在不同情况下的行为。
    • 探索如何在字符串中嵌入变量。
  2. 特殊参数扩展

    • 了解特殊参数(如$?$#$*$@)的含义和用法。
    • $?代表上一个命令的退出状态。
    • $#表示传递给脚本的参数数量。
    • $*$@表示所有参数的列表,但在双引号中表现不同。

更多用法:

详解Shell 脚本中 "" 符号的多种用法_shell-CSDN博客

  1. 高级变量处理

    • 学习使用${VAR:-default}${VAR:+alt_value}等高级替换。
    • 掌握字符串长度${#VAR}和子字符串提取${VAR:offset:length}的用法。
实践任务
  • 任务:编写一个Shell脚本,演示上述各种变量和参数扩展的使用。
bash 复制代码
#!/bin/bash

# 展示特殊参数的用法
echo "Number of arguments: $#"
echo "All arguments with \$*: $*"
echo "All arguments with \$@: $@"

# 展示高级变量处理
DEFAULT_VAR="Default"
echo "${UNSET_VAR:-$DEFAULT_VAR}"
echo "${SET_VAR:+This variable is set}"

# 展示子字符串提取
SAMPLE_STR="Hello World"
echo "Substring: ${SAMPLE_STR:6:5}"
  1. #!/bin/bash

    • 这行是shebang,指明这个脚本应该用bash来执行。
  2. echo "Number of arguments: $#"

    • 打印传递给脚本的参数个数。$#是一个特殊变量,它表示传递给脚本的位置参数的数量。
  3. echo "All arguments with \$*: $*"

    • 打印所有传递给脚本的参数。$*是一个特殊变量,它将所有参数作为一个单一的字符串。
  4. echo "All arguments with \$@: $@"

    • 类似于$*,但$@在被双引号包围时会将每个参数作为独立的字符串。
  5. DEFAULT_VAR="Default"

    • 定义一个变量DEFAULT_VAR并赋值为字符串"Default"
  6. echo "${UNSET_VAR:-$DEFAULT_VAR}"

    • 如果UNSET_VAR没有设置,就使用DEFAULT_VAR的值。这里的:-是参数扩展的一部分,用于提供默认值。
  7. echo "${SET_VAR:+This variable is set}"

    • 如果SET_VAR被设置了,就打印"This variable is set"。这里的:+是参数扩展的一部分,用于在变量被设置时返回替代值。
  8. SAMPLE_STR="Hello World"

    • 定义一个变量SAMPLE_STR并赋值为"Hello World"
  9. echo "Substring: ${SAMPLE_STR:6:5}"

    • 打印SAMPLE_STR的一个子字符串,从第6个字符开始,长度为5。这将结果"World"

这个脚本通过各种示例演示了如何在bash脚本中使用不同类型的参数和变量扩展。这些技巧在处理字符串、参数传递和提供默认值时非常有用。

第3周:引号和字符串处理

学习目标
  • 掌握单引号'、双引号"和反引号`````在Shell脚本中的使用及区别。
学习内容
  1. 单引号和双引号

    • 学习单引号'的使用,了解它是如何阻止变量扩展和特殊字符解释的。
    • 探索双引号"的用法,理解它允许变量扩展但阻止特殊字符(如*?)的解释。
  2. 反引号用于命令替换

    • 理解反引号`````的使用,它用于执行命令并将输出作为字符串。
    • 比较反引号`````与$(...)命令替换的区别和优势。
  3. 字符串拼接和处理

    • 学习如何通过简单地将变量和文字放在一起来拼接字符串。
    • 探索字符串操作技巧,如提取子字符串和字符串长度计算。
实践任务
  • 任务:编写一个脚本,展示单引号、双引号和反引号的使用,以及基本的字符串操作。
bash 复制代码
#!/bin/bash

# 单引号和双引号的使用
VAR="World"
echo 'Hello, $VAR!'     # 单引号,不会扩展变量
echo "Hello, $VAR!"     # 双引号,会扩展变量

# 反引号用于命令替换
CURRENT_DIR=`pwd`
echo "Current directory is $CURRENT_DIR"
ALTERNATE_DIR=$(pwd)
echo "Alternate way to get current dir: $ALTERNATE_DIR"

# 字符串操作
SAMPLE_STR="Hello Shell"
echo "Substring: ${SAMPLE_STR:6}"    # 提取子字符串
echo "String length: ${#SAMPLE_STR}" # 字符串长度
  1. #!/bin/bash

    • 这行是shebang,它指定脚本应该使用bash shell执行。
  2. VAR="World"

    • 这行定义了一个变量VAR并赋值为字符串"World"。
  3. echo 'Hello, $VAR!'

    • 这行演示了单引号的用法。在单引号中,$VAR不会被扩展为其值,因此输出将字面上是Hello, $VAR!
  4. echo "Hello, $VAR!"

    • 这行演示了双引号的用法。在双引号中,$VAR会被扩展为其值(这里是"World"),因此输出将是Hello, World!
  5. CURRENT_DIR=\pwd``

    • 这行使用了反引号来进行命令替换。命令pwd的输出(当前目录的路径)将被赋值给变量CURRENT_DIR
  6. echo "Current directory is $CURRENT_DIR"

    • 这行打印了变量CURRENT_DIR的值,显示当前目录。
  7. ALTERNATE_DIR=$(pwd)

    • 这行也执行了命令替换,但使用了$(...)语法,它是反引号的现代替代方法。这种方法更易读,也更容易嵌套。
  8. echo "Alternate way to get current dir: $ALTERNATE_DIR"

    • 这行打印了使用$(...)命令替换得到的当前目录。
  9. SAMPLE_STR="Hello Shell"

    • 定义了一个新的变量SAMPLE_STR,值为"Hello Shell"。
  10. echo "Substring: ${SAMPLE_STR:6}"

    • 展示了在字符串中提取子字符串的方法。${SAMPLE_STR:6}表示从第6个字符开始提取字符串,因此输出将是"Shell"。
  11. echo "String length: ${#SAMPLE_STR}"

    • 这行展示了如何获取字符串的长度。${#SAMPLE_STR}计算SAMPLE_STR的字符数,输出将是"Hello Shell"的长度。

第4周:重定向和管道符号

学习目标
  • 深入了解Shell中的重定向(>, >>, <)和管道(|)符号的高级用法。
学习内容
  1. 输入输出重定向

    • 掌握标准输出重定向(>>>)的用法。>用于覆盖文件,>>用于追加到文件。
    • 了解标准输入重定向(<)的用法,用于将文件内容作为命令的输入。
  2. 管道符号

    • 学习如何使用管道符号(|)将一个命令的输出作为另一个命令的输入。
    • 探索管道与各种命令(如grep, awk, sed)结合的高级用法。
  3. 错误重定向

    • 了解如何重定向标准错误(2>)。
    • 学习同时重定向标准输出和标准错误的技巧(&>)。
bash 复制代码
#!/bin/bash

# 重定向到文件
echo "Hello, World!" > output.txt

# 追加到文件
echo "Another line" >> output.txt

# 使用管道与grep结合
cat output.txt | grep "Hello"

# 重定向标准错误到文件
ls notexistfile 2> error.log

# 同时重定向标准输出和错误
ls notexistfile &> all_output.log
  1. #!/bin/bash

    • 这行是shebang,指定这个脚本应该使用bash解释器执行。
  2. echo "Hello, World!" > output.txt

    • 这行演示了标准输出重定向。它将echo命令的输出("Hello, World!")重定向到文件output.txt中。如果文件已存在,它会被覆盖;如果不存在,则会被创建。
  3. echo "Another line" >> output.txt

    • 这行也是输出重定向,但使用了>>。它将字符串"Another line"追加到文件output.txt的末尾,而不是覆盖它。
  4. cat output.txt | grep "Hello"

    • 这行展示了管道的使用。cat output.txt命令的输出被作为grep "Hello"命令的输入。这里,grep命令用于从output.txt文件内容中搜索包含"Hello"的行,并输出这些行。
  5. ls notexistfile 2> error.log

    • 这行演示了错误重定向。它尝试列出一个不存在的文件(notexistfile),然后将由此产生的错误信息重定向到error.log文件中。2>用于重定向标准错误(文件描述符2)。
  6. ls notexistfile &> all_output.log

    • 这行同时重定向标准输出和标准错误到all_output.log文件。&>是一个便捷的方法,用于同时捕获和重定向命令的所有输出(包括错误)。

第5周:文件名扩展和通配符

学习目标
  • 理解并掌握Shell中文件名扩展和通配符的使用。
学习内容
  1. 文件名扩展

    • 学习如何使用*(匹配任意多个字符)和?(匹配任意单个字符)进行文件名匹配。
    • 使用方括号[]进行字符集匹配,例如[abc]匹配任意一个字符a、b或c。
  2. 高级通配符

    • 探索花括号扩展{}的使用,例如file{1..3}.txt创建file1.txt, file2.txt, file3.txt
    • 使用更复杂的模式,如[!abc](匹配非a、b、c的任意字符)。
  3. 通配符与命令结合

    • 学习如何将通配符与常用命令结合使用,例如ls, cp, mv等。
    • 掌握通配符在复制(cp)、移动(mv)文件时的用法。
实践任务
  • 任务:编写一个Shell脚本,展示文件名扩展和通配符的高级用法。
bash 复制代码
#!/bin/bash

# 使用*匹配任意文件
echo "Listing all text files:"
ls *.txt

# 使用?匹配单个字符
echo "Listing files with single character:"
ls ?.txt

# 使用[]匹配字符集
echo "Listing files starting with a, b, or c:"
ls [abc]*.txt

# 使用花括号扩展
echo "Creating multiple files:"
touch file{1..3}.txt
  1. #!/bin/bash

    • 这行是shebang,用来指定脚本应该用bash解释器执行。
  2. echo "Listing all text files:"

    • 打印一条消息,说明接下来会列出所有文本文件。
  3. ls *.txt

    • 使用*通配符列出当前目录下所有以.txt结尾的文件。*匹配任意数量的字符。
  4. echo "Listing files with single character:"

    • 打印一条消息,说明接下来会列出文件名为单个字符的文本文件。
  5. ls ?.txt

    • 使用?通配符列出当前目录下文件名由单个字符加上.txt后缀组成的文件。?匹配任意单个字符。
  6. echo "Listing files starting with a, b, or c:"

    • 打印一条消息,说明接下来会列出以a、b或c开头的文本文件。
  7. ls [abc]*.txt

    • 使用方括号[]通配符列出当前目录下所有以a、b或c开头的.txt文件。[abc]匹配任意一个指定的字符(a、b或c)。
  8. echo "Creating multiple files:"

    • 打印一条消息,说明接下来会创建多个文件。
  9. touch file{1..3}.txt

    • 使用花括号扩展创建三个文件:file1.txtfile2.txtfile3.txt{1..3}产生一个从1到3的序列。

第6周:条件测试和表达式

学习目标
  • 掌握在Shell脚本中进行条件测试和算术表达式计算的技巧。
学习内容
  1. 条件测试

    • 学习使用[ ][[ ]]进行条件测试,了解它们之间的差异。
    • 探索如何使用条件测试来比较数字、字符串和文件。
  2. 算术表达式

    • 使用(( ))进行算术运算。
    • 理解算术运算符如+, -, *, /, %的使用。
  3. 高级条件表达式

    • 学习使用><-eq-ne-gt-lt等比较运算符。
    • 掌握字符串比较、文件属性检查等高级条件表达式。
bash 复制代码
#!/bin/bash

# 数字比较
NUM1=3
NUM2=5
if [ $NUM1 -lt $NUM2 ]; then
    echo "$NUM1 is less than $NUM2"
fi

# 字符串比较
STR1="Hello"
STR2="World"
if [[ $STR1 != $STR2 ]]; then
    echo "$STR1 is not equal to $STR2"
fi

# 算术运算
RESULT=$((NUM1 + NUM2))
echo "Sum of NUM1 and NUM2 is $RESULT"
  1. #!/bin/bash

    • 这行是shebang,它指定脚本应该使用bash解释器执行。
  2. NUM1=3NUM2=5

    • 这两行定义了两个变量NUM1NUM2,分别赋值为3和5。
  3. if [ $NUM1 -lt $NUM2 ]; then

    • 这行是一个条件测试语句。它检查NUM1是否小于(-lt,less than)NUM2[ ]用于条件测试。
    • 注意:在Shell脚本中,-lt用于数值比较,而不是数学符号<
  4. echo "$NUM1 is less than $NUM2"

    • 如果NUM1小于NUM2,则执行这条echo命令,输出一条消息。
  5. fi

    • 这行结束if条件块。
  6. STR1="Hello"STR2="World"

    • 定义两个字符串变量STR1STR2,分别赋值为"Hello"和"World"。
  7. if [[ $STR1 != $STR2 ]]; then

    • 这行是另一个条件测试,检查两个字符串是否不相等(!=)。这里使用了[[ ]],这是bash的扩展测试,比[ ]提供了更多的功能。
    • 注意:在双方括号内,您可以使用更多的字符串操作符,如=, !=, <, >等。
  8. echo "$STR1 is not equal to $STR2"

    • 如果STR1STR2不相等,则输出一条消息。
  9. RESULT=$((NUM1 + NUM2))

    • 这行使用了(( ))来进行算术运算。这里计算NUM1NUM2的和,并将结果赋值给变量RESULT
  10. echo "Sum of NUM1 and NUM2 is $RESULT"

    • 打印NUM1NUM2的和。

在Shell脚本中,[ ][[ ]]都用于条件测试,但它们有一些关键区别。这些差异主要体现在语法的灵活性和字符串比较上。

[ ] vs [[ ]] 的区别

  1. 语法宽容性

    • [ ]:更严格。在使用它时,您必须更小心地处理空格和特殊字符。
    • [[ ]]:更灵活。它对空格和特殊字符不那么敏感,使得字符串比较和模式匹配更简单。
  2. 模式匹配和正则表达式

    • [ ]:不支持正则表达式。对模式匹配的支持有限。
    • [[ ]]:支持模式匹配和正则表达式。
  3. 字符串比较

    • [ ]:在进行字符串比较时,需要更多的引号来避免错误。
    • [[ ]]:在比较字符串时更加直观,不需要那么多引号。
  4. 逻辑操作

    • [ ]:逻辑操作符(如&&||)必须在它们自己的方括号内。
    • [[ ]]:允许在一个方括号对内使用多个逻辑操作符。
bash 复制代码
VAR="Hello World"
if [ "$VAR" = "Hello World" ]; then
  echo "Match found"
fi

# 注意:使用`[ ]`时,必须将变量用双引号包围。
bash 复制代码
VAR="Hello World"
if [[ $VAR == "Hello*" ]]; then
  echo "Match found"
fi

# 注意:使用`[[ ]]`时,可以不用双引号,还可以使用通配符。

在这个例子中,[[ ]]允许使用未加引号的变量和模式匹配(如"Hello*"),而[ ]则需要在变量周围加上引号,且不支持模式匹配。

总的来说,[[ ]][ ]更加强大和灵活,特别是在处理字符串和模式匹配时。然而,[[ ]]是bash的扩展功能,不一定在所有的POSIX shell上可用,而[ ]则是标准的POSIX功能。

在Shell脚本中,(( ))( )具有不同的用途和含义,它们用于不同的场景:

(( )) - 算术运算

  • (( ))用于执行算术运算。
  • (( ))中的表达式被视为数学运算,而不是字符串。
  • 可以执行加(+)、减(-)、乘(*)、除(/)、取模(%)等基本算术操作。
  • (( ))中,不需要对变量使用$前缀(除非是赋值操作)。
  • 示例:
bash 复制代码
((result = 5 + 3))  # result变量将被赋值为8

( ) - 子Shell

  • ( )用于创建一个子Shell环境。
  • ( )中执行的命令将在一个新的子Shell中执行,而不是当前的Shell环境。
  • 这意味着在( )中对变量进行的任何修改都不会影响到当前Shell的环境。
  • 子Shell常用于临时改变目录、设置局部变量等。
  • 示例:
bash 复制代码
(cd /tmp && ls)  # 在子Shell中改变目录并列出内容,不影响当前Shell的当前目录

第7周:脚本调试和错误处理

学习目标
  • 掌握在Shell脚本中进行调试和错误处理的技巧。
学习内容
  1. 脚本调试技巧

    • 使用set -x打开调试,显示脚本中执行的每一条命令及其参数。
    • 使用set +x关闭调试。
    • 了解如何使用set -e在脚本中遇到错误时立即退出。
  2. 错误处理

    • 学习使用trap命令捕捉和处理信号及脚本退出。
    • 编写代码以优雅地处理预期外的情况和错误。
  3. 日志记录

    • 实现简单的日志记录机制,记录脚本的运行情况。
    • 使用重定向和tee命令同时输出日志到标准输出和文件。
实践任务
  • 任务:编写一个脚本,其中包含调试命令、错误处理和日志记录。

  • 示例脚本

bash 复制代码
#!/bin/bash

set -e  # 遇到错误时退出
set -x  # 打开调试

trap 'echo "An error occurred."' ERR  # 错误处理

echo "Starting the script..."

# 假设的危险操作
if [ ! -f "/path/to/your/file" ]; then
    echo "File not found!" >&2  # 输出到标准错误
    exit 1
fi

echo "Script completed successfully."

set +x  # 关闭调试

日志记录脚本:

bash 复制代码
#!/bin/bash

# 日志文件路径
LOG_FILE="/path/to/logfile.log"

# 简单的日志记录函数
log() {
    echo "$(date): $@" | tee -a "$LOG_FILE"
}

# 使用log函数记录信息
log "Starting the script..."

# 执行一些操作
log "Running a command..."
ls /some/directory

# 记录脚本结束
log "Script ended successfully."
  • 在这个脚本中,我们定义了一个log函数,用于同时输出日志信息到终端和文件。
  • 通过tee -a命令,日志信息被追加到指定的日志文件。
  • log函数被用于记录脚本的开始、执行的操作和脚本的结束。

echo "$(date): $@" | tee -a "$LOG_FILE"

这行代码是一个日志记录命令,它将消息和时间戳一起输出到终端,并追加到日志文件中。下面是详细的分解:

  1. echo "$(date): $@"

    • echo命令用于输出文本。
    • $(date)是一个命令替换,它执行date命令并将输出(当前日期和时间)嵌入到这个字符串中。
    • :是一个普通字符,用作分隔符。
    • $@是一个特殊的Shell参数,代表所有传递给脚本或函数的参数。在这个上下文中,它将被替换成传递给log函数的所有参数。
    • 因此,这部分代码将生成像这样的输出:"Mon Sep 7 12:00:01 UTC 2023: Your log message"。
  2. | tee -a "$LOG_FILE"

    • |是一个管道符号,它将echo命令的输出传递给tee命令。
    • tee命令读取标准输入(在这里是来自echo命令的输出),并将其写入到文件和标准输出(通常是终端)。
    • -a选项指示tee追加文本到文件,而不是覆盖文件。
    • "$LOG_FILE"是日志文件的路径。如果你之前定义了LOG_FILE="/path/to/logfile.log",那么tee会把输入的文本追加到这个文件。
相关推荐
幂简集成4 分钟前
如何免费调用GPT API进行自然语言处理
gpt·api
小黑爱编程38 分钟前
【LInux】HTTPS是如何实现安全传输的
linux·安全·https
BeyondESH43 分钟前
Linux线程同步—竞态条件和互斥锁(C语言)
linux·服务器·c++
鱼饼6号1 小时前
Prometheus 上手指南
linux·运维·centos·prometheus
Asher Gu1 小时前
Linux系统编程入门 | 模拟实现 ls -l 命令
linux
c无序1 小时前
【Linux进程控制】进程程序替换
linux
潮汐退涨月冷风霜2 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习
GoppViper2 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
羊小猪~~2 小时前
深度学习基础案例5--VGG16人脸识别(体验学习的痛苦与乐趣)
人工智能·python·深度学习·学习·算法·机器学习·cnn
Charles Ray3 小时前
C++学习笔记 —— 内存分配 new
c++·笔记·学习