Linux shell 脚本攻略之统计文件的行数、单词数和字符数

本文摘自《Linux Shell脚本攻略》,深入探讨了Shell脚本的基础知识及高级技巧,为读者提供了丰富的实战案例,帮助读者掌握Shell脚本编程的核心技能。

摘自:《Linux shell 脚本攻略》

image

转载于:https://www.cnblogs.com/pengdonglin137/p/3528086.html

<think>我们有两个引用,用户的问题是如何在shell脚本统计文件行数。引用[1]展示了使用find结合wcawk统计多个文件行数的方法,引用[2]则展示了一个shell脚本,通过循环遍历文件并过滤掉空行注释行来统计代码行数。 用户的问题是如何在shell脚本统计文件行数,我们可以提供多种方法,包括: 1. 使用wc命令直接统计单个文件行数。 2. 统计多个文件行数(不区分文件)。 3. 统计多个文件中每个文件行数以及总。 4. 在统计时排除空行注释行(如引用[2])。 我们将按照以下结构回答: 一、基本方法:使用wc命令 二、统计多个文件行数 三、统计目录下特定类型文件行数(递归) 四、排除空行注释行(统计有效代码行) 五、在shell脚本中的完整示例 注意:在shell脚本中,我们需要注意命令的健壮性,比如处理文件不存在的情况。 开始回答: # Shell 脚本统计文件行数的方法 在 Shell 脚本中,统计文件行数是常见的任务,例如分析代码量或日志规模。常用的工具是 `wc`(word count)命令,它不仅可以统计行数,还可以统计单词字符数。下面详细介绍几种统计行数的方法,并提供可复用的脚本示例。 ## 一、基本方法:使用 `wc` 命令 `wc -l` 命令用于统计文件行数。基本用法如下: ```bash wc -l filename ``` 输出格式为:`行数 文件名`,例如: ```bash $ wc -l example.txt 120 example.txt ``` 如果只需要行数字(不包含文件名),可以使用以下方法: ```bash wc -l < filename ``` 或者: ```bash cat filename | wc -l ``` 这两种方法只输出字,便于在脚本中赋值给变量: ```bash lines=$(wc -l < example.txt) echo "文件行数: $lines" ``` ## 二、统计多个文件行数 如果需要统计多个文件的总行数(不区分文件),可以使用以下命令: ```bash wc -l file1.txt file2.txt | awk 'END{print $1}' ``` 或者使用更高效的方法(避免处理中间文件名): ```bash cat file1.txt file2.txt | wc -l ``` 但注意,如果文件很大,使用 `cat` 可能会占用较多内存。替代方案是使用 `awk` 直接求: ```bash wc -l file1.txt file2.txt | awk '{sum += $1} END {print sum}' ``` ## 三、递归统计目录下特定类型文件行数 当需要统计一个目录及其子目录中所有特定类型文件(如所有 `.txt` 文件)的行数时,可以结合 `find` `wc` 命令。 引用[1]提供了一种方法: ```bash find . -name "*.txt" -not -name "*.json" -exec wc -l {} + | awk '{sum += $1} END {print sum}' ``` 解释: - `find . -name "*.txt"`:查找当前目录下所有 `.txt` 文件。 - `-not -name "*.json"`:排除 `.json` 文件(可选,根据需求调整)。 - `-exec wc -l {} +`:对找到的文件执行 `wc -l` 命令。 - `awk '{sum += $1} END {print sum}'`:累加每个文件行数并输出总。 ## 四、排除空行注释行(统计有效代码行) 在统计代码行数时,通常需要排除空行注释行。引用[2]的脚本展示了如何排除以 `#` 或 `//` 开头的行以及空行: ```bash line=$(egrep -v '(^#|^//|^$)' ${file_name} | wc -l) ``` 我们可以修改这个命令以适应不同的注释风格(如 `#`、`//`、`/* */` 等)。但注意,多行注释的处理比较复杂,以下示例仅处理单行注释空行。 ### 示例:统计 Python 文件的有效行数(排除空行以 `#` 开头的行) ```bash file="example.py" effective_lines=$(grep -v '^#\|^$' "$file" | wc -l) ``` ### 示例:统计 C 语言文件的有效行数(排除空行以 `//` 或 `/*` 开头的行,但注意 `/*` 可能跨行) 由于跨行注释难以用单行命令处理,简单场景下可以只排除 `//` 空行: ```bash file="example.c" effective_lines=$(grep -v '^//\|^$' "$file" | wc -l) ``` 对于复杂情况,建议使用专门的代码统计工具(如 `cloc`)。 ## 五、在 Shell 脚本中的完整示例 以下是一个可复用的 Shell 脚本,用于统计指定目录下特定类型文件行数(可选择是否排除注释行空行)。 ```bash #!/bin/bash # 统计文件行数脚本 # 检查参 if [ $# -lt 1 ]; then echo "用法: $0 <目录> [文件扩展名] [是否排除注释空行(yes/no)]" exit 1 fi dir="$1" ext="${2:-*}" # 默认所有文件 exclude="${3:-no}" # 默认不排除 total_lines=0 # 查找文件统计 while IFS= read -r -d $'\0' file; do if [ "$exclude" = "yes" ]; then # 根据文件类型排除注释空行(这里以扩展名判断,简单示例) case "$file" in *.py|*.sh) lines=$(grep -v '^#\|^$' "$file" | wc -l) ;; *.c|*.cpp|*.h|*.java) lines=$(grep -v '^//\|^/\*\|^\*\|^$' "$file" | wc -l) ;; *) lines=$(wc -l < "$file") ;; esac else lines=$(wc -l < "$file") fi total_lines=$((total_lines + lines)) echo "$file: $lines 行" done < <(find "$dir" -type f -name "*.$ext" -print0) echo "总行数: $total_lines" ``` ### 脚本说明: 1. **参处理**: - `$1`:要统计的目录。 - `$2`:文件扩展名(如 `txt`、`py`),默认所有文件。 - `$3`:是否排除注释空行(`yes` 或 `no`),默认 `no`。 2. **文件查找**:使用 `find` 命令递归查找文件,`-print0` `while IFS= read -r -d $'\0'` 处理文件中的空格。 3. **行数统计**: - 根据 `exclude` 参决定是否过滤注释行。 - 针对不同文件类型(如 `.py`、`.c`)使用不同的过滤规则。 4. **累加总行数**:将每个文件行数累加到 `total_lines`。 ### 使用示例: ```bash # 统计当前目录下所有 .py 文件行数(排除注释空行) bash count_lines.sh . py yes ``` ## 注意事项 - **性能**:对于大目录,使用 `-print0` `read -d $'\0'` 可以安全处理文件中的空格特殊字符。 - **跨行注释**:上述脚本对跨行注释(如 C 语言的 `/* ... */`)的处理不完善,复杂场景建议使用 `cloc` 等专业工具。 - **错误处理**:脚本中未处理文件读取错误,可添加权限检查。 总之,`wc` 是统计行数的核心工具,结合 `find`、`grep` `awk` 可以实现灵活的统计需求。根据实际场景选择简单统计或有效代码行统计。 §§相关问题§§ 1. 如何用 `awk` 单独统计每个文件行数并显示文件名? 2. 在 Shell 脚本中如何处理文件中的空格或特殊字符? 3. 如何用 `cloc` 工具统计代码行数? 4. 如何排除特定目录(如 `.git`)在行数统计之外? 5. 如何优化大文件行数统计的性能?</think># Shell 脚本统计文件行数的方法 在 Shell 脚本统计文件行数是常见任务,特别是在代码分析、日志处理等场景。以下是多种实用的统计方法,结合了引用中的最佳实践: ## 一、基本行数统计方法 ### 1. 使用 `wc -l` 命令 ```bash # 统计单个文件 line_count=$(wc -l < filename.txt) echo "文件行数: $line_count" # 统计多个文件 wc -l file1.txt file2.txt ``` ### 2. 统计目录下所有文件行数 ```bash # 统计当前目录所有.txt文件的总行数(排除.json文件) find . -name "*.txt" -not -name "*.json" -exec wc -l {} + | awk '{sum += $1} END {print sum}' [^1] ``` **说明**: - `find`: 递归查找文件 - `-exec wc -l {} +`: 对找到的文件执行行数统计 - `awk`: 累加所有文件行数 ## 二、统计有效代码行数(排除注释空行) 引用[2]提供了统计有效代码行的实用脚本: ```bash #!/bin/bash # 检查参 if [ $# -ne 2 ]; then echo "用法: $0 <代码目录> <文件扩展名>" exit 1 fi CODE_DIR="$1" # 代码目录 CODE_TYPE="$2" # 文件扩展名(如 py, js, java) total_line=0 echo "开始统计 $CODE_DIR 目录下 .$CODE_TYPE 文件的有效代码行数..." # 遍历所有指定类型的文件 while IFS= read -r -d $'\0' file; do # 排除注释行(#, //)空行 lines=$(grep -Ev '^\s*(#|//|$)' "$file" | wc -l) total_line=$((total_line + lines)) echo "$file: $lines 行" done < <(find "$CODE_DIR" -name "*.$CODE_TYPE" -type f -print0) echo "有效代码总行数: $total_line" [^2] ``` **使用示例**: ```bash bash count_lines.sh ~/projects py ``` ## 三、高级统计技巧 ### 1. 按文件类型分组统计 ```bash find . -type f -name "*.py" -exec wc -l {} + | awk 'END{print "Python 总行数:", $1}' find . -type f -name "*.js" -exec wc -l {} + | awk 'END{print "JavaScript 总行数:", $1}' ``` ### 2. 排除特定目录(如.git) ```bash find . -path ./.git -prune -o -name "*.java" -exec wc -l {} + | awk '{sum+=$1} END{print "Java代码总行数:", sum}' ``` ### 3. 带进度显示的统计 ```bash total_files=$(find . -name "*.go" | wc -l) counter=0 while IFS= read -r file; do counter=$((counter+1)) printf "处理中: %d/%d 文件\r" "$counter" "$total_files" wc -l "$file" >> tmp.txt done < <(find . -name "*.go") awk '{sum+=$1} END{print "总行数:", sum}' tmp.txt ``` ## 四、性能优化建议 1. **大文件处理**: ```bash # 使用高效工具 awk 'END{print NR}' huge_file.log ``` 2. **并行处理**: ```bash find . -name "*.log" | parallel -j 4 'wc -l {}' | awk '{sum+=$1} END{print sum}' ``` 3. **内存优化**: ```bash # 避免将大文件加载到内存 grep -c ^ huge_file.csv ``` ## 五、注意事项 1. 文件名包含空格时,使用 `-print0` `read -d $'\0'` 2. 符号链接处理:`find -L` 包含符号链接指向的文件 3. 跨平台兼容:macOS 的 `wc` 与 Linux 有差异,建议安装 `gwc`(GNU coreutils) > 对于大型项目,推荐使用专业工具如 `cloc`(Count Lines of Code),支持130+种语言: > `cloc --exclude-dir=node_modules,dist .`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值