2011-10-31 29 views
8

Tôi đang cố gắng sử dụng lệnh grep trong một kịch bản python bằng cách sử dụng mô-đun subprocess.Python Subprocess Grep

Dưới đây là những gì tôi có:

userid = 'foo12' 
p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE) 

Và nó sẽ trả về không có gì. Tôi không hoàn toàn chắc chắn những gì tôi đang làm sai để ai đó có thể vui lòng giải thích. Phương pháp hiện tại mà tôi đang sử dụng công trình đó là bằng cách thêm shell = true để làm cho nó xuất kết quả chính xác nhưng khi các trang trợ giúp đã chỉ ra rằng nó không an toàn. Tôi cần giúp đỡ để thực hiện công việc này để kịch bản của tôi không an toàn.

Trả lời

9

Tôi nghĩ bạn chạy lên chống lại hai vấn đề:

  1. cuộc gọi này:

    p = subprocess.Popen(['grep', "%s *.log"%userid]... 
    

    wil l không hoạt động như mong đợi mà không có shell=True vì danh sách các đối số đang được chuyển trực tiếp đến os.execvp, yêu cầu mỗi mục phải là một chuỗi đại diện cho một đối số. Bạn đã phân tách hai đối số riêng biệt với nhau thành một chuỗi đơn (nói cách khác, grep diễn giải "foo12 *.log" làm mẫu để tìm kiếm chứ không phải danh sách tệp mẫu +).

    Bạn có thể khắc phục điều này bằng cách nói:

    p = subprocess.Popen(['grep', userid, '*.log']...) 
    
  2. Vấn đề thứ hai là, một lần nữa mà không shell=True, execvp không biết những gì bạn có ý nghĩa bởi *.log và vượt qua nó trực tiếp cùng với grep, mà không đi qua cơ chế mở rộng ký tự đại diện của vỏ. Nếu bạn không muốn sử dụng shell=True, bạn có thể thực hiện một số việc như:

    import glob 
    args = ['grep', userid] 
    args.extend(glob.glob('*.log') 
    p = subprocess.Popen(args, ...) 
    
7

Dưới đây là hai mảnh kiểm tra mã để mô hình từ:

>>> print subprocess.check_output(['grep', 'python', 'api_talk.txt']) 
Discuss python API patterns 
Limitations of python 
Introspection in python 

>>> print subprocess.check_output('grep python *.txt', shell=True) 

Sử dụng sau này nếu bạn muốn vỏ để làm mở rộng ký tự đại diện cho bạn. Khi shellĐúng, hãy đảm bảo đặt toàn bộ lệnh trong một chuỗi chứ không phải danh sách các trường riêng biệt.

4

Tôi giả sử bạn muốn grep cho 'foo12' trong tất cả các file kết thúc bằng '.log', để có được điều này để làm việc với chỉ subprocess bạn sẽ cần phải thay đổi mã của bạn như sau:

userid = 'foo12' 
p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True) 

shell=True là cần thiết để mở rộng ký tự đại diện và khi tùy chọn đó được đặt, bạn cần phải cung cấp lệnh chuỗi thay vì danh sách.

Ngoài ra, hãy chắc chắn rằng khi bạn đang cung cấp một danh sách các đối số mà mỗi đối số là một lối đi riêng trong danh sách, mã ban đầu của bạn sẽ là tương đương như sau:

grep 'foo12 *.log' 
Các vấn đề liên quan