如何在 Shell 脚本中打印变量的值

ShellBeginner
立即练习

介绍

Shell 脚本是 Linux 环境中自动化任务的强大工具。Shell 编程中的一项基本技能是使用变量——用于保存数据的临时存储位置。本教程将指导你完成在 shell 脚本中创建变量并打印其值的过程。通过完成这个实验(Lab),你将了解如何声明变量、访问它们的值,并将它们合并到实用的 shell 脚本中。

使用变量创建你的第一个 Shell 脚本

让我们从创建一个简单的 shell 脚本开始,它演示了如何声明和使用变量。

什么是 Shell 变量?

Shell 变量是命名的存储位置,可以在 shell 脚本中保存值。它们允许你存储和检索数据,例如文本字符串、数字、文件路径和命令输出。变量使你的脚本更灵活且可重用。

创建你的第一个脚本

让我们创建一个 shell 脚本文件:

  1. 打开 WebIDE 终端

  2. 导航到项目目录(如果尚未在此目录中):

    cd ~/project
    
  3. 使用 WebIDE 编辑器创建一个名为 myscript.sh 的新文件:

    • 单击 WebIDE 中的“新建文件”图标
    • 将其命名为 myscript.sh
    • 将以下内容添加到文件中:
    #!/bin/bash
    
    ## This is my first shell script with variables
    
    ## Declaring a variable
    name="LabEx User"
    
    ## Printing the variable
    echo "Hello, $name!"
    
    ## Printing the current date using a variable
    current_date=$(date)
    echo "Today is: $current_date"
    
  4. 按 Ctrl+S 或单击文件 > 保存来保存文件

  5. 使用以下命令使脚本可执行:

    chmod +x myscript.sh
    
  6. 运行你的脚本:

    ./myscript.sh
    

    你应该看到类似这样的输出:

    Hello, LabEx User!
    Today is: Thu Jul 13 10:30:45 UTC 2023
    

理解脚本

让我们分解一下脚本中发生了什么:

  1. 第一行 #!/bin/bash(称为 shebang)告诉系统使用 Bash shell 来执行脚本。
  2. 我们创建了一个名为 name 的变量,并使用 name="LabEx User" 将其赋值为 "LabEx User"。
  3. 我们使用 echo "Hello, $name!" 打印了变量的值。变量名之前的 $ 符号告诉 shell 替换变量的值。
  4. 我们创建了另一个变量 current_date,并使用 $(date) 将其赋值为 date 命令的输出。
  5. 我们打印了 current_date 变量的值。

变量命名规则

在 shell 脚本中创建变量时,请遵循以下命名约定:

  • 变量名可以包含字母、数字和下划线
  • 它们必须以字母或下划线开头
  • 赋值时,等号周围不允许有空格
  • 变量名区分大小写(NAME、name 和 Name 是三个不同的变量)

尝试修改脚本以包含你自己的变量,然后再次运行它以查看结果。

打印变量值的不同方法

现在你已经了解了创建变量的基础知识,让我们探索在 shell 脚本中打印它们值的不同方法。

使用双引号

打印变量最常用的方法是使用双引号和 echo 命令。双引号允许 shell 解释变量名并替换它们的值。

创建一个名为 print_variables.sh 的新文件:

  1. 单击 WebIDE 中的“新建文件”图标

  2. 将其命名为 print_variables.sh

  3. 添加以下内容:

    #!/bin/bash
    
    ## Declaring variables
    name="LabEx"
    version=1.0
    is_active=true
    
    ## Printing variables with double quotes
    echo "Application name: $name"
    echo "Version: $version"
    echo "Active status: $is_active"
    
    ## Printing multiple variables in one statement
    echo "The $name application version $version is $is_active"
    
  4. 保存文件(Ctrl+S 或文件 > 保存)

  5. 使其可执行:

    chmod +x print_variables.sh
    
  6. 运行脚本:

    ./print_variables.sh
    

    你应该看到类似这样的输出:

    Application name: LabEx
    Version: 1.0
    Active status: true
    The LabEx application version 1.0 is true
    

使用花括号

有时你需要更精确地说明变量名开始和结束的位置。花括号通过清楚地界定变量名来帮助实现这一点。

将以下行添加到你的 print_variables.sh 脚本中:

## Using curly braces to clearly define variable boundaries
app="${name}App"
echo "Application full name: $app"

## This avoids confusion when you want to append text directly to a variable's value
echo "Application name with text: ${name}Text"

保存并再次运行脚本:

./print_variables.sh

额外的输出应该显示:

Application full name: LabExApp
Application name with text: LabExText

使用单引号

与双引号不同,单引号会阻止变量替换并打印字面文本。

将这些行添加到你的脚本中:

## Using single quotes (no variable substitution)
echo 'With single quotes: $name is not replaced'

## Mixing quote types for complex output
echo "This is the variable value: '$name'"

保存并再次运行脚本。你应该看到:

With single quotes: $name is not replaced
This is the variable value: 'LabEx'

使用 printf 进行格式化输出

printf 命令提供了对输出格式的更多控制:

## Using printf for formatted output
printf "Name: %s\nVersion: %.1f\n" "$name" "$version"

## Formatting numbers with printf
number=42.5678
printf "Formatted number: %.2f\n" $number

保存并再次运行脚本。额外的输出将显示:

Name: LabEx
Version: 1.0
Formatted number: 42.57

尝试使用不同的打印方法,看看哪种方法最适合你的需求。

创建一个带有用户输入的实用 Shell 脚本

现在,让我们创建一个更实用的 shell 脚本,它接受用户输入,将其存储在变量中,并显示结果。

读取用户输入

read 命令允许你的脚本接受来自用户的输入。让我们创建一个简单的问候脚本:

  1. 创建一个名为 greeting.sh 的新文件:

    • 单击 WebIDE 中的“新建文件”图标
    • 将其命名为 greeting.sh
    • 添加以下内容:
    #!/bin/bash
    
    ## Simple greeting script that takes user input
    
    ## Prompt the user for their name
    echo "What is your name?"
    read username
    
    ## Prompt for age
    echo "How old are you?"
    read age
    
    ## Display a greeting with the provided information
    echo "Hello, $username! You are $age years old."
    
    ## Calculate birth year (approximately)
    current_year=$(date +%Y)
    birth_year=$((current_year - age))
    
    echo "You were born around the year $birth_year."
    
    ## Adding a personalized message based on age
    if [ $age -lt 18 ]; then
      echo "You are a minor."
    elif [ $age -ge 18 ] && [ $age -lt 65 ]; then
      echo "You are an adult."
    else
      echo "You are a senior."
    fi
    
  2. 保存文件(Ctrl+S 或文件 > 保存)

  3. 使其可执行:

    chmod +x greeting.sh
    
  4. 运行脚本:

    ./greeting.sh
    
  5. 当提示时,输入你的姓名和年龄。你应该看到基于你输入的个性化输出。

理解脚本组件

让我们分解一下这个脚本的关键部分:

  1. read 命令将用户输入存储在变量中(usernameage)。
  2. 我们在 echo 语句中使用变量来创建个性化输出。
  3. 我们使用 $((expression)) 语法执行算术运算来计算出生年份。
  4. 我们使用条件语句(ifelifelse)根据年龄值提供不同的消息。
  5. 我们使用带有格式化选项的 date 命令来获取当前年份。

使脚本更具交互性

让我们增强我们的脚本,使其更具交互性和实用性。将以下内容添加到你的 greeting.sh 文件中:

## Ask if the user wants to see the current system information
echo "Would you like to see some system information? (yes/no)"
read response

## Convert the response to lowercase for easier comparison
response_lower=$(echo "$response" | tr '[:upper:]' '[:lower:]')

if [ "$response_lower" = "yes" ] || [ "$response_lower" = "y" ]; then
  echo "System information for user $username:"
  echo "-------------------------------------"
  echo "Hostname: $(hostname)"
  echo "Kernel version: $(uname -r)"
  echo "System uptime: $(uptime -p)"
  echo "CPU information: $(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | sed 's/^[ \t]*//')"
  echo "Memory available: $(free -h | grep Mem | awk '{print $7}')"
  echo "-------------------------------------"
else
  echo "No problem, $username. Have a great day!"
fi

保存文件并再次运行它:

./greeting.sh

按照提示操作,并在被问及是否要查看系统信息时输入“yes”。你应该看到有关系统的详细信息。

此脚本演示了如何:

  • 读取和处理用户输入
  • 存储和操作变量
  • 执行计算
  • 根据变量值做出决策
  • 执行系统命令并将其输出存储在变量中
  • 向用户显示格式化的输出

尝试修改脚本以添加更多交互功能或不同类型的系统信息。

创建用于文件操作的 Shell 脚本

让我们应用我们对 shell 变量的了解,创建一个执行文件操作的有用脚本。此脚本将演示变量如何帮助自动化文件管理任务。

创建备份脚本

让我们创建一个脚本,用于备份指定目录中的文件:

  1. 首先,让我们创建一个测试目录和一些示例文件来使用:

    mkdir -p ~/project/test_files
    echo "This is file 1" > ~/project/test_files/file1.txt
    echo "This is file 2" > ~/project/test_files/file2.txt
    echo "This is file 3" > ~/project/test_files/file3.txt
    
  2. 现在,创建一个名为 backup.sh 的新文件:

    • 单击 WebIDE 中的“新建文件”图标
    • 将其命名为 backup.sh
    • 添加以下内容:
    #!/bin/bash
    
    ## A script to backup files from a source directory to a backup directory
    
    ## Define variables for directories
    source_dir="$HOME/project/test_files"
    backup_dir="$HOME/project/backup"
    date_stamp=$(date +"%Y%m%d_%H%M%S")
    backup_name="backup_$date_stamp"
    
    ## Print the script's purpose
    echo "File Backup Script"
    echo "==================="
    echo "Source directory: $source_dir"
    echo "Backup directory: $backup_dir/$backup_name"
    
    ## Create the backup directory if it doesn't exist
    if [ ! -d "$backup_dir" ]; then
      echo "Creating backup directory: $backup_dir"
      mkdir -p "$backup_dir"
    fi
    
    ## Create a timestamped backup directory
    mkdir -p "$backup_dir/$backup_name"
    
    ## Check if source directory exists
    if [ ! -d "$source_dir" ]; then
      echo "Error: Source directory $source_dir does not exist!"
      exit 1
    fi
    
    ## Count the number of files in the source directory
    file_count=$(ls -1 "$source_dir" | wc -l)
    echo "Found $file_count files in the source directory."
    
    ## Copy the files to the backup directory
    echo "Copying files to backup location..."
    cp -r "$source_dir"/* "$backup_dir/$backup_name"
    
    ## Verify the copy operation
    copied_count=$(ls -1 "$backup_dir/$backup_name" | wc -l)
    echo "Copied $copied_count files to the backup directory."
    
    ## Check if all files were copied successfully
    if [ "$file_count" -eq "$copied_count" ]; then
      echo "Backup completed successfully!"
    else
      echo "Warning: Not all files were copied. Please check for errors."
    fi
    
    ## List the contents of the backup directory
    echo "Contents of the backup directory:"
    ls -la "$backup_dir/$backup_name"
    
    ## Display the total size of the backup
    backup_size=$(du -sh "$backup_dir/$backup_name" | cut -f1)
    echo "Total backup size: $backup_size"
    
  3. 保存文件(Ctrl+S 或文件 > 保存)

  4. 使其可执行:

    chmod +x backup.sh
    
  5. 运行脚本:

    ./backup.sh
    

    你应该看到显示备份过程的输出,包括:

    • 源目录和备份目录
    • 找到的文件数
    • 复制操作的确认
    • 备份目录的内容
    • 备份的总大小

理解脚本

此备份脚本演示了几个重要的概念:

  1. 变量使用:我们使用变量来存储目录路径、时间戳和计数
  2. 命令替换:我们使用 $(command) 语法来捕获变量中的命令输出
  3. 条件语句:我们使用 if 语句来检查目录是否存在
  4. 字符串操作:我们使用时间戳创建一个唯一的备份名称
  5. 路径变量:我们使用 $HOME 来引用用户的主目录
  6. 命令执行:我们在脚本中使用 shell 命令,如 mkdircpls
  7. 退出代码:我们使用 exit 1 以错误状态终止脚本

增强备份脚本

让我们修改我们的脚本以接受来自用户的自定义源目录:

  1. 在编辑器中打开 backup.sh

  2. 将内容替换为以下内容:

    #!/bin/bash
    
    ## A script to backup files from a source directory to a backup directory
    
    ## Check if a source directory was provided
    if [ $## -eq 0 ]; then
      ## No argument provided, use default directory
      source_dir="$HOME/project/test_files"
      echo "No source directory specified, using default: $source_dir"
    else
      ## Use the provided directory
      source_dir="$1"
      echo "Using specified source directory: $source_dir"
    fi
    
    ## Define variables for directories
    backup_dir="$HOME/project/backup"
    date_stamp=$(date +"%Y%m%d_%H%M%S")
    backup_name="backup_$date_stamp"
    
    ## Print the script's purpose
    echo "File Backup Script"
    echo "==================="
    echo "Source directory: $source_dir"
    echo "Backup directory: $backup_dir/$backup_name"
    
    ## Create the backup directory if it doesn't exist
    if [ ! -d "$backup_dir" ]; then
      echo "Creating backup directory: $backup_dir"
      mkdir -p "$backup_dir"
    fi
    
    ## Create a timestamped backup directory
    mkdir -p "$backup_dir/$backup_name"
    
    ## Check if source directory exists
    if [ ! -d "$source_dir" ]; then
      echo "Error: Source directory $source_dir does not exist!"
      exit 1
    fi
    
    ## Count the number of files in the source directory
    file_count=$(ls -1 "$source_dir" | wc -l)
    echo "Found $file_count files in the source directory."
    
    ## Copy the files to the backup directory
    echo "Copying files to backup location..."
    cp -r "$source_dir"/* "$backup_dir/$backup_name"
    
    ## Verify the copy operation
    copied_count=$(ls -1 "$backup_dir/$backup_name" | wc -l)
    echo "Copied $copied_count files to the backup directory."
    
    ## Check if all files were copied successfully
    if [ "$file_count" -eq "$copied_count" ]; then
      echo "Backup completed successfully!"
    else
      echo "Warning: Not all files were copied. Please check for errors."
    fi
    
    ## List the contents of the backup directory
    echo "Contents of the backup directory:"
    ls -la "$backup_dir/$backup_name"
    
    ## Display the total size of the backup
    backup_size=$(du -sh "$backup_dir/$backup_name" | cut -f1)
    echo "Total backup size: $backup_size"
    
  3. 保存文件

  4. 使用自定义目录运行脚本:

    ./backup.sh ~/project
    

    增强的脚本现在演示了:

    • 使用 $1 的命令行参数(传递给脚本的第一个参数)
    • 未提供参数时的默认值
    • 使用 $# 的参数检查(参数数量)

    此备份脚本是一个实用的示例,说明了如何使用 shell 变量来创建用于自动化文件管理任务的有用、灵活的工具。

总结

在这个实验中,你已经学习了在 shell 脚本中使用变量的基本技能:

  • 创建和声明 shell 变量
  • 使用 echo、printf 和引号打印变量值的不同方法
  • 读取和处理用户输入
  • 使用 shell 变量执行计算
  • 使用变量进行文件操作和备份任务
  • 处理命令行参数

这些技能为 shell 脚本编写奠定了坚实的基础,并将使你能够创建更具动态性和灵活性的脚本,以自动化 Linux 环境中的各种任务。在你的 shell 脚本编写旅程中,你可以基于这些概念构建更复杂的脚本,用于系统管理、文件管理和数据处理任务。