2015-12-22 4 views
0

Я хочу, чтобы извлечь строки из File1, которые не присутствуют в Файл2Как я выполнить команду комм Linux в Python

FILE1

a 
b 
c 

file2

a 
c 

поэтому выход должен быть :

b 

Один из возможных команд в Баш:

comm -23 <(sort File1) <(sort File2) > File 

И это прекрасно работает в Баш, но я не знаю, как правильно реализовать в Python.

Я попытался с

import os 
os.system("comm -23 <(sort File1) <(sort File2) > File") 

И не работает. Подсказка?

+0

Сделайте себе одолжение и используйте 'subprocess' –

+0

Как это будет реализовано подпроцессом? @ padraic-cunningham – josifoski

+1

Зачем беспокоиться? Вы можете реализовать эту логику изначально на Python, так что очень легко ... –

ответ

3

Если вы должны использовать оболочку, сделать это безопасно:

subprocess.call(['bash', '-c', 
    'comm -23 <(sort "$1") <(sort "$2") >"$3"', '_', 
    infile1_name, infile2_name, outfile_name]) 

То есть: Вместо того чтобы передавать имена файлов, как часть вашего кода, передайте их как не посещающих так что их имена не могут интерпретироваться оболочкой.

+0

для деталей, я должен принять ваш ответ. – josifoski

7

Как насчет чистого решения python?

with open('file1', 'r') as f: 
    lines1 = set(f.read().splitlines()) 

with open('file2', 'r') as f: 
    lines2 = set(f.read().splitlines()) 

print(lines1.difference(lines2)) 

Или с меньшими затратами памяти:

with open('file1') as f, open('file2') as f2: 
    lines1 = set(map(str.rstrip, f)) 
    print(lines1.difference(map(str.rstrip, f2))) 
+0

tnx :) +1, будет пересмотрено будет чистое решение python или стиль bash – josifoski

+0

почему бы просто не называть набор объектов, а не создавать несколько копий данных? –

+0

Зависит от того, хотите ли вы концы в наборах. Я не хотел их. – MaxNoe

2

Это не работает, потому что нужно использовать bash запустить команду:

os.system("bash -c 'comm -23 <(sort File1) <(sort File2) > File'") 

Обычно, os.system() использование sh запустить команду. Но, однако, между bash и sh.

Так что в этом случае я использовал bash -c 'command' вызов bash запустите команду. Тогда это может сработать.

В руководстве bash:

-c Если параметр -c присутствует, то команды считываются из первого, не являющегося параметром аргумента command_string.

Если есть аргументы после command_string, они назначаются позиционным параметрам, начиная с $0.

+0

Мое место отлично работает! – josifoski

+2

Существует угроза безопасности для этого - посмотрите, что произойдет, если один из ваших имен файлов содержит буквальную строку '$ (rm -rf ~)'. –

+0

поэтому кроссплатформенное лучше, чем ослиное направление. Tnx за советом – josifoski