如何用Shell脚本提取C文件中的函数名?
Hey there! I see you've already got the loop going to traverse all .c files—great start! Let's figure out how to extract those function declarations and format the output exactly as you want.
Method 1: Using Awk with Regular Expressions (Quick & Simple)
This method works for most basic C function declarations. It uses a regex to match common function patterns and formats the output as requested.
Here's the complete script:
#!/bin/bash # Check if a directory argument is provided if [ $# -ne 1 ]; then echo "Usage: $0 <target-directory>" exit 1 fi # Traverse all .c files in the target directory for file in $(find "$1" -type f -name '*.c'); do # Use awk to extract and format function declarations awk ' # Match lines that look like function declarations (skip single-line comments) /^[[:space:]]*[a-zA-Z0-9_]+[[:space:]]+[a-zA-Z0-9_]+[[:space:]]*\(/ && !/\/\// { # Remove any inline /* ... */ comments sub(/\/\*.*/, "", $0) # Trim extra whitespace (optional but cleaner) gsub(/[[:space:]]+/, " ", $0) # Output the full file path followed by the function declaration print "'"$file"' " $0 } ' "$file" done
How This Works:
- Argument Check: First we make sure the user provides exactly one directory path to avoid errors.
- Safe File Traversal: Using
"$1"and quoting variables ensures we handle file paths with spaces correctly. - Awk Regex: The regex matches lines that start with optional whitespace, followed by a return type, function name, and opening parenthesis—while skipping lines with
//comments. - Cleanup: We strip inline
/* ... */comments and reduce multiple spaces to a single one for cleaner output.
Limitations:
This regex won't handle edge cases like:
- Multi-line function declarations
- Complex return types (e.g.,
int (*get_function())()) - Functions declared inside macros or comments
Method 2: Using Ctags (More Reliable for Complex Code)
If you need to handle all valid C function declarations (including tricky ones), ctags is the way to go. It's a dedicated tool for parsing code and extracting symbols like functions.
First, make sure ctags is installed (most Linux distros have it by default; on macOS, use brew install universal-ctags).
Here's the script:
#!/bin/bash if [ $# -ne 1 ]; then echo "Usage: $0 <target-directory>" exit 1 fi # Traverse .c files and use ctags to extract functions find "$1" -type f -name '*.c' | while read -r file; do # Use ctags to get function symbols, then format the output ctags -x --c-kinds=f "$file" | awk -v full_path="$file" '{ # Reconstruct the function declaration (name + parameters) decl = $1 "(" $3 ")" # Prepend the full file path print full_path " " decl }' done
Why This Is Better:
- Accurate Parsing: Ctags understands C syntax, so it correctly handles multi-line declarations, complex return types, and typedefs.
- Consistent Results: No need to tweak regex for edge cases—it just works for valid C code.
Example Output
For your sample files, both methods will produce:
/directory/path/game.c int main() /directory/path/hello.c int something()
内容的提问来源于stack exchange,提问作者ian

