44
55
66def main ():
7- # --------------------------------------------------------
8- # Set up argparse
9- # --------------------------------------------------------
107 parser = argparse .ArgumentParser (
118 prog = "wc" ,
129 description = "wc command implementation in python"
@@ -20,74 +17,62 @@ def main():
2017
2118 args = parser .parse_args ()
2219
23- # --------------------------------------------------------
24- # Ensures at least one path exists
25- # --------------------------------------------------------
2620 if len (args .paths ) == 0 :
2721 print ("wc: no file specified" , file = sys .stderr )
2822 sys .exit (1 )
2923
3024 totals = {"lines" : 0 , "words" : 0 , "chars" : 0 }
3125
32- # --------------------------------------------------------
33- # Loop over each file path and process it
34- # --------------------------------------------------------
26+ no_flags = not args .l and not args .w and not args .c
27+ width = 7
28+
29+ def format_output (counts , label ):
30+ if no_flags :
31+ return f"{ counts ['lines' ]:> {width }} { counts ['words' ]:>{width }} { counts ['chars' ]:>{width }} { label } "
32+
33+ parts = []
34+ if args .l :
35+ parts .append (f"{ counts ['lines' ]:>{width }} " )
36+ if args .w :
37+ parts .append (f"{ counts ['words' ]:>{width }} " )
38+ if args .c :
39+ parts .append (f"{ counts ['chars' ]:>{width }} " )
40+
41+ return f"{ '' .join (parts )} { label } "
42+ had_error = False
43+
3544 for file_path in args .paths :
3645 try :
37- with open (file_path , "r" , encoding = "utf-8 " ) as f :
38- content = f .read ()
46+ with open (file_path , "rb " ) as f :
47+ data = f .read ()
3948 except OSError as err :
4049 print (f"wc: cannot read file'{ file_path } ': { err } " , file = sys .stderr )
50+ had_error = True
4151 continue
4252
43- # --------------------------------------------------------
44- # Count values
45- # --------------------------------------------------------
46- line_count = len (content .split ("\n " ))
53+ content = data .decode ("utf-8" , errors = "replace" )
54+
55+ line_count = content .count ("\n " )
4756
4857 words = [w for w in re .split (r"\s+" , content ) if w ]
4958 word_count = len (words )
59+ char_count = len (data )
5060
51- char_count = len ( content )
61+ counts = { "lines" : line_count , "words" : word_count , "chars" : char_count }
5262
5363 totals ["lines" ] += line_count
5464 totals ["words" ] += word_count
5565 totals ["chars" ] += char_count
5666
57- # --------------------------------------------------------
58- # Decide what to print based on flags
59- # --------------------------------------------------------
60- no_flags = not args .l and not args .w and not args .c
67+ print (format_output (counts , file_path ))
6168
62- if no_flags :
63- print (f"{ line_count } { word_count } { char_count } { file_path } " )
64- continue
65-
66- if args .l :
67- print (f"{ line_count } { file_path } " )
68-
69- if args .w :
70- print (f"{ word_count } { file_path } " )
71-
72- if args .c :
73- print (f"{ char_count } { file_path } " )
74-
75-
76- # --------------------------------------------------------
77- # Print totals if there are multiple files
78- # --------------------------------------------------------
7969 if len (args .paths ) > 1 :
8070 no_flags = not args .l and not args .w and not args .c
8171
8272 if no_flags :
83- print (f" { totals [ 'lines' ] } { totals [ 'words' ] } { totals [ 'chars' ] } total" )
73+ print (format_output ( totals , " total") )
8474
85- if args .l :
86- print (f"{ totals ['lines' ]} total" )
87- if args .w :
88- print (f"{ totals ['words' ]} total" )
89- if args .c :
90- print (f"{ totals ['chars' ]} total" )
75+ sys .exit (1 if had_error else 0 )
9176
9277if __name__ == "__main__" :
9378 main ()
0 commit comments