Shell脚本基础应用

1.脚本运行方法

复制代码
创建目录
[root@localhost opt]# mkdir learn
复制代码
执行文件的方法

[root@localhost opt]# cd learn/
[root@localhost learn]# ls
[root@localhost learn]# vi hello.sh
[root@localhost learn]# .hello.sh
[root@localhost learn]# vi hello.sh
[root@localhost learn]# .hello.sh
[root@localhost learn]# vi hello.sh
[root@localhost learn]# .hello.sh
[root@localhost learn]# vi hello.sh
[root@localhost learn]# source hello.sh
helloworld!
[root@localhost learn]# . hello.sh
helloworld!
[root@localhost learn]# bash hello.sh 
helloworld!
[root@localhost learn]# ll
total 4
-rw-r--r--. 1 root root 59 Oct  6 07:12 hello.sh
[root@localhost learn]# chmod u+x hello.sh 
[root@localhost learn]# ll
total 4
-rwxr--r--. 1 root root 59 Oct  6 07:12 hello.sh
[root@localhost learn]# ./hello.sh 
helloworld!
[root@localhost learn]# 

2.脚本传入参数

复制代码
#!/usr/bin/bash
#这是注释,用#号
echo "helloworld!"
echo "一共有 $# 个参数"
#在Shell中,最多只能有9个参数
echo "第一个参数是 $1"
echo "第二个参数是 $2"
echo "第十个参数是 $10"

如果参数超过10个该怎么处理?

复制代码
在 Shell 脚本中,当参数超过 9 个时,不能直接使用 $10、$11 这样的形式,因为 Shell 会将 $10 解释为 $1 后面跟一个 0。

#使用数组:
#!/bin/bash

# 将所有参数保存到数组
args=("$@")

# 通过数组下标访问参数
echo "第10个参数: ${args[9]}"
echo "第11个参数: ${args[10]}"
echo "第12个参数: ${args[11]}"

# 遍历所有参数
for i in "${!args[@]}"; do
    echo "参数 $((i+1)): ${args[i]}"
done
复制代码
#!/bin/bash

# 在 bash 4.0+ 和现代 shell 中支持 ${10} 形式
echo "第10个参数: ${10}"
echo "第11个参数: ${11}"
echo "第12个参数: ${12}"
复制代码
#!/usr/bin/bash
#通过参数来确定对某个文件进行查找,并输出相应的行号和行数,只接收1个参数
filename=$1
grep -n root $filename

请完善以下脚本,明确提醒用户,如果输入参数错误,则给予及时提醒。

复制代码
#!/usr/bin/bash

while true; do
    # 清屏(可选)
    # clear
    
    echo "=== 文件内容查找工具 ==="
    echo "请输入要查找的文件路径(输入 'q' 退出):"
    read -p "文件: " filename
    
    # 检查是否退出
    if [ "$filename" = "q" ] || [ "$filename" = "quit" ]; then
        echo "再见!"
        exit 0
    fi
    
    # 检查文件是否存在
    if [ ! -e "$filename" ]; then
        echo "错误:文件 '$filename' 不存在!"
        echo "请检查文件路径后重试。"
        echo ""
        read -p "按回车键继续..."
        continue
    fi
    
    # 检查是否是普通文件
    if [ ! -f "$filename" ]; then
        echo "错误:'$filename' 不是一个普通文件!"
        echo ""
        read -p "按回车键继续..."
        continue
    fi
    
    # 检查文件是否可读
    if [ ! -r "$filename" ]; then
        echo "错误:没有读取文件 '$filename' 的权限!"
        echo ""
        read -p "按回车键继续..."
        continue
    fi
    
    # 检查文件是否为空
    if [ ! -s "$filename" ]; then
        echo "警告:文件 '$filename' 为空!"
        echo ""
        read -p "按回车键继续..."
        continue
    fi
    
    # 执行查找操作
    echo ""
    echo "在文件 '$filename' 中查找包含 'root' 的行:"
    echo "=============================================="
    grep -n "root" "$filename"
    
    # 检查grep执行结果
    grep_result=$?
    if [ $grep_result -eq 0 ]; then
        echo "=============================================="
        echo "查找完成。"
    elif [ $grep_result -eq 1 ]; then
        echo "--------------------------------------------------"
        echo "未找到包含 'root' 的行。"
        echo "=============================================="
    else
        echo "=============================================="
        echo "查找过程中出现错误。"
    fi
    
    echo ""
    echo "是否继续查找其他文件?"
    read -p "输入 'q' 退出,或按回车键继续: " choice
    if [ "$choice" = "q" ] || [ "$choice" = "quit" ]; then
        echo "再见!"
        exit 0
    fi
done

3.引号的特殊用法

复制代码
关键要点总结:
单引号: 所有字符原样输出,不进行任何替换
双引号: 允许变量替换和命令替换,保护空格和特殊字符
反引号`: 命令替换,但推荐使用 $()
转义字符: 使用 \ 来转义特殊字符
引号嵌套: 混合使用单双引号来处理复杂情况
数组和参数: 总是用双引号引用变量,特别是包含空格的变量

#!/bin/bash

echo "=================================================="
echo "          Shell引号特殊用法详解脚本"
echo "=================================================="
echo

# 1. 单引号 - 完全原样输出
echo "1. 单引号用法 - 完全原样输出:"
echo '单引号内的所有字符都保持原样: $HOME `date` "hello"'
echo

# 2. 双引号 - 允许变量和命令替换
echo "2. 双引号用法 - 允许变量和命令替换:"
name="Shell用户"
echo "Hello, $name! 当前用户: $USER, 时间: $(date '+%H:%M:%S')"
echo

# 3. 反引号 - 命令替换(推荐使用$()代替)
echo "3. 反引号用法 - 命令替换:"
echo "当前目录文件列表: `ls | head -3`"
echo "等价写法: $(ls | head -3)"
echo

# 4. 转义字符 - 特殊字符处理
echo "4. 转义字符用法:"
echo "这是一个换行符: 第一行\n第二行\t带制表符"
echo -e "使用-e选项解析转义: 第一行\n第二行\t带制表符"
echo

# 5. 引号嵌套使用
echo "5. 引号嵌套使用:"
echo "双引号内包含单引号: \"这是一个'单引号'在双引号内\""
echo '单引号内包含双引号: '\''这是一个"双引号"在单引号内'\'
echo

# 6. 变量中的引号处理
echo "6. 变量中的引号处理:"
file_list="file1.txt file2.txt 'special file.txt'"
echo "文件列表: $file_list"
# 正确处理带空格的文件名
for file in $file_list; do
    echo "  文件: $file"
done
echo

# 7. Here Document 中的引号
echo "7. Here Document 用法:"
cat << EOF
这是一个Here Document示例
变量不会被替换: \$HOME = $HOME
可以包含多行内容
EOF
echo

# 8. Here Document 带引号
echo "8. 带引号的Here Document:"
cat << 'EOF'
这个Here Document使用单引号
变量完全原样: $HOME
命令也不会执行: $(date)
EOF
echo

# 9. 引号在函数参数中的使用
echo "9. 函数参数中的引号使用:"

process_args() {
    echo "参数个数: $#"
    local i=1
    for arg in "$@"; do
        echo "  参数$i: $arg"
        ((i++))
    done
}

echo "不带引号传递参数:"
process_args hello world with spaces

echo "带引号传递参数:"
process_args "hello world" "with spaces" "special\"char"
echo

# 10. 引号在数组中的使用
echo "10. 数组中的引号使用:"
files=("normal.txt" "file with spaces.txt" "special'quote.txt")

echo "数组内容:"
for file in "${files[@]}"; do
    if [ -e "$file" ] || touch "$file" 2>/dev/null; then
        echo "  文件: $file - 创建成功"
    else
        echo "  文件: $file - 创建失败"
    fi
done
echo

# 11. 引号在条件判断中的使用
echo "11. 条件判断中的引号使用:"
test_string="hello world"

if [ "$test_string" = "hello world" ]; then
    echo "字符串匹配成功"
else
    echo "字符串匹配失败"
fi

# 处理可能为空的变量
empty_string=""
if [ -z "$empty_string" ]; then
    echo "空字符串检测成功"
fi
echo

# 12. 引号在命令执行中的重要性
echo "12. 命令执行中的引号重要性:"
echo "创建测试文件..."
echo "test content" > "test file.txt"

echo "不加引号(会出错):"
ls -l test file.txt 2>&1 | head -1

echo "加引号(正确):"
ls -l "test file.txt"
echo

# 13. 特殊字符处理
echo "13. 特殊字符处理:"
special_chars='$`\"!@#$%^&*()'
echo "特殊字符: $special_chars"
echo '单引号中的特殊字符: $`\"!@#$%^&*()'
echo

# 14. 实际应用示例 - 查找文件
echo "14. 实际应用 - 文件查找:"
find . -name "*.txt" -type f -exec echo "找到文件: '{}'" \; 2>/dev/null | head -3
echo

# 15. 实际应用示例 - JSON处理
echo "15. 实际应用 - JSON字符串处理:"
json_data='{"name": "John", "age": 30, "city": "New York"}'
echo "JSON数据: $json_data"
# 使用jq解析(如果已安装)
if command -v jq &> /dev/null; then
    echo "$json_data" | jq '.name'
else
    echo "jq命令未安装,跳过JSON解析演示"
fi
echo

# 清理临时文件
cleanup() {
    rm -f "test file.txt" "normal.txt" "file with spaces.txt" "special'quote.txt"
    echo "临时文件已清理"
}

cleanup

echo "=================================================="
echo "                  演示结束"
echo "=================================================="

4.特殊用法

①特殊变量

复制代码
Shell脚本中$*和$@的区别
不加引号时:$* 和 $@ 行为相同
加双引号时:
	"$*":所有参数合并为一个字符串
	"$@":每个参数保持独立
在循环中:使用 "$@" 可以正确处理带空格的参数
最佳实践:在需要保留参数原样时,总是使用 "$@"

$*:将所有参数作为一个整体字符串处理
$@:将每个参数作为独立的字符串处理
shell 复制代码
#!/bin/bash

echo "=== 演示 \$* 和 \$@ 的区别 ==="
echo

# 设置一些测试参数
set -- "arg 1" "arg 2" "arg 3"

echo "参数列表: $@"
echo "参数个数: $#"
echo

echo "1. 直接使用 \$* 和 \$@:"
echo "使用 \$*: $*"
echo "使用 \$@: $@"
echo

echo "2. 在双引号中使用:"
echo "使用 \"\$*\": \"$*\""
echo "使用 \"\$@\": \"$@\""
echo

echo "3. 使用for循环遍历 \$*:"
echo -n "   "
for arg in $*; do
    echo -n "[$arg] "
done
echo
echo

echo "4. 使用for循环遍历 \$@:"
echo -n "   "
for arg in $@; do
    echo -n "[$arg] "
done
echo
echo

echo "5. 使用for循环遍历 \"\$*\":"
echo -n "   "
for arg in "$*"; do
    echo -n "[$arg] "
done
echo
echo

echo "6. 使用for循环遍历 \"\$@\":"
echo -n "   "
for arg in "$@"; do
    echo -n "[$arg] "
done
echo
echo

echo "7. 显示参数个数:"
echo "   参数总数: $#"
echo "   \$* 作为整体时的参数个数: 1"
echo "   \$@ 拆分时的参数个数: $#"
echo

echo "8. 实际应用示例:"
echo "   将参数传递给另一个函数"

# 定义一个测试函数
test_function() {
    echo "   在函数内参数个数: $#"
    echo "   在函数内参数列表: $@"
}

echo "   使用 \"\$*\" 传递:"
test_function "$*"

echo "   使用 \"\$@\" 传递:"
test_function "$@"

5.expr表达式

6.test命令

①test文件

②逻辑处理

shell 复制代码
[yt@localhost ~]$ [ -e /etc/passwd ]
[yt@localhost ~]$ echo $?
0
[yt@localhost ~]$ [ -e /etc/passwd -a -e /etc/group ]
[yt@localhost ~]$ echo $?
0
[yt@localhost ~]$ [ -e /etc/passwd -a -e /etc/groupp ]
[yt@localhost ~]$ echo $?
1
[yt@localhost ~]$ [ -e /etc/passwd -o -e /etc/groupp ]
[yt@localhost ~]$ echo $?
0
[yt@localhost ~]$ [ ! -e /etc/passwd ]
[yt@localhost ~]$ echo $?
1

③test字符串

④test数值

相关推荐
LCG元4 分钟前
Linux 性能优化实战:当服务器负载飙升1000%时,我做了什么?
linux
众俗16 分钟前
Linux+Docker+SpringBoot 简单部署
linux·spring boot·docker
染指秃头32 分钟前
VM虚拟机共享宿主机代理(Ubuntu24.04)
linux·运维·服务器
Wang's Blog33 分钟前
Linux小课堂: Squid代理缓存服务器部署与访问控制实战指南
linux·服务器·缓存
梁正雄1 小时前
7-linux命令-用户管理
linux
江公望1 小时前
磁盘分区方案GPT和MBR的区别浅谈
linux
priority_key1 小时前
TCP 如何保证传输的可靠性?
服务器·网络·后端·网络协议·tcp/ip
qsjming1 小时前
RTNETLINK answers: File exists问题分析
网络·rtnetlink
2401_841495641 小时前
黑客攻击基础知识
网络·黑客·操作系统·web·计算机结构·应用程序·黑客攻击
交换机路由器测试之路1 小时前
发包工具anysend使用手册
网络·测试工具·ipv6·发包工具