Bash提取指定关键字后首词实现:获取Shell脚本依赖命令
Bash脚本依赖提取优化方案
需求说明
需要编写Bash脚本分析其他Bash脚本的全部依赖项,提取规则如下:
- 输出每行换行后的第一个词
- 输出管道符
|之后出现的第一个词 - 输出子shell标识
$(之后出现的第一个词 - 忽略所有注释内容
- 通用要求:可输出任意指定
<key>之后出现的第一个词
示例参考
输入脚本内容
#!/bin/bash # My script printf "Hello World\n" # First line strings <<< "Hello World" | awk '{print $1}' | sed 's/Hello/Goodbye/' echo $(cat <<< "Hello World")
期望输出
printf strings awk sed echo cat
现有实现问题
当前实现需要多次遍历文件,性能较低,现有代码:
sed 's/|/\n/g; s/#/\n#/g; s/\$(/\n/g' ${FILENAME} \ | sed 's/^[ \t]*//; /^#/d' \ | awk '{print $1}' \ | sort -u
优化实现(单次遍历)
直接用awk单次处理即可,一次遍历完成所有规则匹配、注释过滤、结果输出:
awk ' { # 先删除当前行的所有注释内容 sub(/#.*/, "") # 按管道符、子shell标识分割当前行 n = split($0, parts, /\||\$\(/) for (i=1; i<=n; i++) { # 去除片段前后的空白字符 gsub(/^[ \t]+|[ \t]+$/, "", parts[i]) # 提取片段第一个有效命令词 if (parts[i] ~ /^[a-zA-Z0-9_\-\/]/) { split(parts[i], words, /[ \t]/) if (words[1] != "") print words[1] } } } ' "${FILENAME}" | sort -u
优化说明
- 全程仅读取文件1次,所有逻辑在同一个awk进程内完成,相比原实现减少了多进程管道开销和多次IO读取开销,大文件下性能提升明显
- 注释过滤逻辑更严谨:直接删除每行
#之后的所有内容,不会误处理字符串中包含的#字符 - 规则可扩展性强:需要新增匹配规则时,直接修改
split的正则分隔符即可,不需要新增遍历逻辑 - 自动忽略空片段、特殊开头的无效内容,避免输出空行或错误结果
内容的提问来源于stack exchange,提问作者Lenna
相关产品推荐
相关产品推荐

