Как использовать команду Linux в Python с функциями Python (sys.argv) - PullRequest
1 голос
/ 24 июня 2019

В моем скрипте на python мне нужно использовать 'awk', но я хочу передать файл с помощью sys.argv. Мой текущий код выглядит так:

import sys
import os

cmd="awk '/regex/ {print}' sys.argv[1] | sed 's/old/new/g'"
x=os.popen(cmd).read()

Теперь проблема в том, что sys.argv - это вещь, написанная на python, но переменная cmd использует команду linux. Поэтому мой вопрос - есть ли способ включить sys.argv в мою команду linux?

Ответы [ 3 ]

2 голосов
/ 24 июня 2019

Вам действительно не нужен Awk или sed для этого.Python может делать эти вещи естественным образом, элегантно, гибко, надежно и естественно.

import sys
import re

r = re.compile(r'regex')
s = re.compile(r'old')

with open(sys.argv[1]) as input:
    for line in input:
        if r.search(line):
            print(s.sub('new', line))

Если вы действительно хотите использовать подпроцессы для чего-то, просто используйте общие функции Python для интерполяции строк, где вам нужно вставить значениепеременной Python в строку.

import subprocess
import sys
import shlex

result = subprocess.run(
    """awk '/regex/ {print}' {} | 
    sed 's/old/new/g'""".format(shlex.quote(sys.argv[1])),
    stdout=subprocess.PIPE,
    shell=True, check=True)
print(subprocess.stdout)

Но на самом деле не делайте этого.Если вы действительно не можете избежать подпроцесса, сделайте его как можно более простым (избегайте shell=True и снимите все части, которые могут быть выполнены в Python).

1 голос
/ 24 июня 2019

Просто попробуй вот так

cmd="awk '/regex/ {print}' " + str(sys.argv[1]) + " | sed 's/old/new/g'"
x=os.popen(cmd).read()

0 голосов
/ 24 июня 2019

Ваш лучший выбор - реализовать вашу логику как чистую логику Python, как описано в первой части ответа @ tripleee . Ваш второй лучший выбор - сохранить внешние инструменты, но исключить необходимость использования оболочки для их вызова и соединения.

См. Раздел документации по Python Замена конвейеров оболочки .

import sys
from subprocess import Popen, PIPE

p1 = Popen(['awk', '/regex/ {print}'], stdin=open(sys.argv[1]), stdout=PIPE)
p2 = Popen(['sed', 's/old/new/g'], stdin=p1.stdout, stdout=PIPE)
x = p2.communicate()[0]

Ваш третий лучший выбор - сохранить оболочку, но передать данные вне кода из кода:

p = subprocess.run([
  """awk '/regex/ {print}' <"$1" | sed 's/old/new/'""",  # code to run
  '_',                                                   # $0 in context of that code
  sys.argv[1]                                            # $1 in context of that code
], shell=True, check=True, stdout=subprocess.PIPE)
print(p.stdout)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...