循环与函数
目标
以实际可用的形式掌握循环与函数。尤其要确保脚本在‘没有匹配文件’、‘参数中包含空格’、‘完全没有参数’等边界情况下也不会出错。
为什么重要
shell 函数不返回值。计算结果通过标准输出传出,成功或失败则通过退出码表示。只有遵守这一约定,才能自然地写出 if is_number "$x" 这样的用法。处理文件列表时也不要解析 ls,而应交给 shell 的 glob——$(ls *.log) 遇到包含空格的文件名时会出错,没有匹配项时还会把错误消息送入循环。改用 glob 后,又会出现没有匹配项时模式字符串原样保留的另一种陷阱,因此需要 [ -f "$f" ] || continue 这道防线。
步骤
- 创建
/root/bin/loop1.sh,逐行输出从1到5。 - 创建
/root/loops/logs目录,在其中放置 4 个.log文件和 2 个.txt文件。再创建/root/bin/count.sh <디렉터리>,只输出该目录直属的.log文件数量。传入空目录时必须输出 0。 - 在
/root/loops/users.csv中按이름,역할格式写入至少 3 行,再创建/root/bin/readcsv.sh,读取该文件并按이름(역할)格式逐行输出(不带参数运行)。 - 在
/root/bin/lib.sh中定义slugify函数,把单词转成小写并用连字符连接。/root/bin/use.sh必须通过 source 加载该文件后使用函数。use.sh Hello World->hello-world。 - 创建
/root/bin/isnum.sh <문자열>。字符串只由数字组成时返回退出码 0,否则返回非 0。**不能输出任何内容。**空字符串、正负号和小数点都不算数字。 - 创建
/root/bin/each.sh,将收到的每个参数按[인자]格式逐行输出。each.sh "a b" c必须输出两行。没有参数时不输出任何内容。 - 创建
/root/bin/sum.sh,输出所有数字参数的总和。没有参数时输出0。 - 创建
/root/bin/summary.sh <디렉터리>,用以下两行输出该目录中的.log文件数量和总行数。files=<개수>total_lines=<합계>
提示
. /root/bin/lib.sh与source /root/bin/lib.sh是同一条命令。它不会创建新进程,因此函数定义会保留下来。wc -l < 파일不会在输出中附带文件名,便于参与计算。- 常见错误 1:第 2 步和第 8 步传入空目录时,glob 不会展开,模式字符串会原样保留,导致数量变成 1。
- 常见错误 2:第 6 步使用
for x in $*,会把"a b"拆成两个参数。
输出 1 到 5
创建 /root/bin/loop1.sh,逐行输出从 1 到 5。
可以使用 for x in 1 2 3 4 5,也可以使用花括号展开 {1..5}。
使用 glob 统计文件
创建 /root/loops/logs 目录,在其中放置 4 个 .log 文件和 2 个 .txt 文件。再创建 /root/bin/count.sh <디렉터리>,只输出该目录直属的 .log 文件数量。传入空目录时必须输出 0。
没有匹配文件时,模式字符串会原样保留。请用 [ -f "$f" ] || continue 将其过滤掉。
逐行读取 CSV
在 /root/loops/users.csv 中按 이름,역할 格式写入至少 3 行,再创建 /root/bin/readcsv.sh,读取该文件并按 이름(역할) 格式逐行输出(不带参数运行)。
使用 while IFS=, read -r a b 这种形式,并在 done 后通过重定向提供输入。
把函数拆分到库中
在 /root/bin/lib.sh 中定义 slugify 函数,把单词转成小写并用连字符连接。/root/bin/use.sh 必须通过 source 加载该文件后使用函数。use.sh Hello World -> hello-world。
在 lib.sh 中定义函数,再从 use.sh 使用 . 或 source 加载。不能复制粘贴函数。
通过退出码进行判断
创建 /root/bin/isnum.sh <문자열>。字符串只由数字组成时返回退出码 0,否则返回非 0。**不能输出任何内容。**空字符串、正负号和小数点都不算数字。
如果输出判断结果,就无法直接用于 if 语句。只通过 return 0 / return 1 表示结果。
安全遍历含空格的参数
创建 /root/bin/each.sh,将收到的每个参数按 [인자] 格式逐行输出。each.sh "a b" c 必须输出两行。没有参数时不输出任何内容。
比较 for x in "$@" 与 for x in $* 的差异。没有参数时必须什么也不做。
对可变参数求和
创建 /root/bin/sum.sh,输出所有数字参数的总和。没有参数时输出 0。
不要忘记把累加变量初始化为 0。没有参数时必须输出 0。
目录摘要报告
创建 /root/bin/summary.sh <디렉터리>,用以下两行输出该目录中的 .log 文件数量和总行数。
files=<개수>total_lines=<합계>
同时统计文件数和总行数。即使目录为空,也必须输出 0/0。