sn62

Finished
11def grep(pattern: str, flags: str, files: list[str]) -> str:
2 pass
2 """
3 Search files for lines matching a search string and return all matching lines.
4
5 Args:
6 pattern (str): The string to search for
7 flags (str): Space-separated flags that modify search behavior
8 files (list[str]): List of file paths to search in
9
10 Returns:
11 str: Matching lines, possibly with file names and line numbers prepended
12
13 Flags:
14 -n: Prepend line numbers
15 -l: Output only file names
16 -i: Case-insensitive matching
17 -v: Invert matching
18 -x: Match entire line only
19 """
20 # Parse flags - handle both space-separated and concatenated flags
21 flag_list = []
22 if flags:
23 # Handle concatenated flags like "-ni" as well as space-separated
24 for flag in flags.split():
25 if flag.startswith('-') and len(flag) > 1:
26 # Add each character as a separate flag (except the dash)
27 for char in flag[1:]:
28 flag_list.append('-' + char)
29 else:
30 flag_list.append(flag)
31
32 line_numbers = '-n' in flag_list
33 files_only = '-l' in flag_list
34 case_insensitive = '-i' in flag_list
35 invert_match = '-v' in flag_list
36 exact_match = '-x' in flag_list
37
38 # Prepare pattern for case-insensitive matching
39 search_pattern = pattern.lower() if case_insensitive else pattern
40
41 # Results storage
42 results = []
43 matching_files = set()
44
45 # Process each file
46 for file_path in files:
47 try:
48 with open(file_path, 'r', encoding='utf-8') as file:
49 lines = file.readlines()
50 except FileNotFoundError:
51 # Edge Case: File not found - skip the file
52 continue
53 except Exception:
54 # Edge Case: Other file reading errors - skip the file
55 continue
56
57 file_has_match = False
58
59 # Process each line
60 for line_num, line in enumerate(lines, 1):
61 # Prepare line for comparison
62 compare_line = line.lower() if case_insensitive else line
63
64 # Determine if line matches
65 if exact_match:
66 # Edge Case: Exact match flag - match entire line (excluding newline)
67 line_content = compare_line.rstrip('\n\r')
68 matches = (search_pattern == line_content)
69 else:
70 # Edge Case: Substring match - search pattern anywhere in line
71 matches = (search_pattern in compare_line)
72
73 # Apply invert flag
74 if invert_match:
75 # Edge Case: Invert match flag - flip the match result
76 matches = not matches
77
78 # Process match
79 if matches:
80 file_has_match = True
81
82 if files_only:
83 # Edge Case: Files only flag - we only need to know which files match
84 matching_files.add(file_path)
85 break # No need to check more lines in this file
86 else:
87 # Build output line
88 output_line = ""
89
90 # Add file name if multiple files
91 if len(files) > 1:
92 # Edge Case: Multiple files - prepend filename
93 output_line += f"{file_path}:"
94
95 # Add line number if requested
96 if line_numbers:
97 # Edge Case: Line numbers flag - prepend line number
98 output_line += f"{line_num}:"
99
100 # Add the actual line content
101 output_line += line
102
103 results.append(output_line)
104
105 # If files_only and this file had a match, add it
106 if files_only and file_has_match:
107 # Edge Case: Files only mode - collect matching file names
108 matching_files.add(file_path)
109
110 # Return appropriate result based on flags
111 if files_only:
112 # Edge Case: Files only flag - return sorted file names
113 # When -l flag is used, return each filename only once, with trailing newlines
114 if matching_files:
115 return "\n".join(sorted(matching_files)) + "\n"
116 else:
117 return ""
118 else:
119 # Edge Case: Normal operation - return matching lines
120 # Ensure trailing newline for non-empty results, except when last line already has one
121 if results:
122 output = "".join(results)
123 # Add trailing newline if the output doesn't already end with one
124 if not output.endswith('\n'):
125 output += "\n"
126 return output
127 else:
128 return ""
129
130# Handled Edge Cases: Empty pattern, empty files list, file not found, other file reading errors, exact match flag, substring match, invert match flag, files only flag, multiple files, line numbers flag, case insensitive flag, files only mode, normal operation"
Test NameStatus
test_multiple_files_no_matches_various_flags
Pass
test_multiple_files_one_match_match_entire_lines_flag
Pass
test_multiple_files_one_match_multiple_flags
Pass
test_multiple_files_one_match_no_flags
Pass
test_multiple_files_one_match_print_file_names_flag
Pass
test_multiple_files_several_matches_case_insensitive_flag
Pass
test_multiple_files_several_matches_file_flag_takes_precedence_over_line_number_flag
Pass
test_multiple_files_several_matches_inverted_and_match_entire_lines_flags
Pass
test_multiple_files_several_matches_inverted_flag
Pass
test_multiple_files_several_matches_no_flags
Pass
test_multiple_files_several_matches_print_line_numbers_flag
Pass
test_one_file_no_matches_various_flags
Pass
test_one_file_one_match_case_insensitive_flag
Pass
test_one_file_one_match_file_flag_takes_precedence_over_line_flag
Pass
test_one_file_one_match_match_entire_lines_flag
Pass
test_one_file_one_match_multiple_flags
Pass
test_one_file_one_match_no_flags
Pass
test_one_file_one_match_print_file_names_flag
Pass
test_one_file_one_match_print_line_numbers_flag
Pass
test_one_file_several_matches_case_insensitive_flag
Pass
test_one_file_several_matches_inverted_and_match_entire_lines_flags
Pass
test_one_file_several_matches_inverted_flag
Pass
test_one_file_several_matches_match_entire_lines_flag
Pass
test_one_file_several_matches_no_flags
Pass
test_one_file_several_matches_print_line_numbers_flag
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.