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数值
