2013-05-09 3 views
0

웃지 마세요. 기본 VM의 호스트 이름과 IP를 대체 할 간단한 스크립트를 작성하려고합니다. 나는이 작업 버전을 가지고 있지만 더 읽기 쉽고 간결하게 만들려고 노력하고있다. 아래 코드를 시도 할 때 구문 오류가 발생합니다. 필자는 이러한 목록 작성을 시도했지만 파일 유형이므로 작동하지 않습니다. 미리 감사드립니다.목록 이해가없는 for 루프의 conc

try: 
    old_network = open("/etc/sysconfig/network", "r+") 
    new_network = open("/tmp/network", "w+") 
    replacement = "HOSTNAME=" + str(sys.argv[1]) + "\n" 

    shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak') 
    for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line) 
    for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line) 
    os.rename("/tmp/network","/etc/sysconfig/network") 
    print 'Hostname set to', str(sys.argv[1]) 
except IOError, e: 
    print "Error %s" % e 
    pass 
+0

그래서 무엇을하려고합니까? 기능을 짧게합니까? 또한 일부 [Zen of Python] (http://www.python.org/dev/peps/pep-0020/) 원칙을 꽤 폭력적으로 위반하는 것입니다. 예를 들어,'for' 루프를 모두 한 줄짜리 문장으로 보여주는 대신 실제 블록으로 만들어야합니다. –

+0

작업 코드를 게시하십시오. 현재 버전이해야 할 일이 어느 정도 명확하지 않습니다. –

+0

Martijin의 회신에서 작성된 내용을 수행해야합니다. 코드는 원래 제안 된대로 블록에 포함되었습니다. 나는 목록의 이해력에 관해 읽었고 나는 거기의 형식을 좋아한다. 나는 for-loops와 비슷한 문구가있을 것이라고 생각했다. – numb3rs1x

답변

3

당신은 여기에 몇 가지 이상한 구문을 사용하고 있습니다 :

for line in old_network: new_network.write(line) if not re.match(("HOSTNAME"), line) 
for line in old_network: new_network.write(replacement) if re.match(("HOSTNAME"), line) 

당신은 거기 if 문을 역, 별도의 라인이를 둘 필요가;

for line in old_network: 
    if not re.match("HOSTNAME", line): 
     new_network.write(line) 
    else: 
     new_network.write(replacement) 

당신은 입력 파일을 통해 정말 루프가 두 번 (파일로 아무것도 할 것이 두 번째 루프는 이미 전체에 읽은 수 있습니다 : 당신은 당신이 너무 if 문을 단순화 할 수있는 루프를 결합해야).

다음으로 열려있는 파일 객체 컨텍스트 관리자 (with 사용)를 사용하여 문제가 발생해도 제대로 닫히는 지 확인하십시오. 파일 모드에서 +을 삭제할 수 있습니다. 혼합 모드에서 파일을 사용하고 있지 않으며, 읽기 및 쓰기를 위해 아직 열기 전에 가장 먼저 백업 복사본을 작성하는 것이 가장 좋습니다.

정규 표현식을 사용할 필요가 없습니다. 간단한 을 입력하거나 line.strip().startswith('HOSTNAME')을 입력하여 으로 시작하고 HOSTNAME으로 시작하는지 확인해야합니다.

사용은 tempfile module 충돌하지 않는 이름을 가진 임시 파일을 만들려면 다음

from tempfile import NamedTemporaryFile 

shutil.copyfile('/etc/sysconfig/network', '/etc/sysconfig/network.setup_bak') 

replacement = "HOSTNAME={}\n".format(sys.argv[1]) 
new_network = NamedTemporaryFile(mode='w', delete=False) 

with open("/etc/sysconfig/network", "r") as old_network, new_network: 
    for line in old_network: 
     if line.lstrip().startswith('HOSTNAME'): 
      line = replacement 
     new_network.write(line) 

os.rename(new_network.name, "/etc/sysconfig/network") 
print 'Hostname set to {}'.format(sys.argv[1]) 

당신은 당신이 단순히 인쇄하여 파일의 내용을 대체 할 수있는 fileinput module를 사용하여이 작업을 더욱 단순화 할 수 있습니다;

이 12 대 코드의 6 개 라인 (안 세고 수입)의
import fileinput 
import sys 

replacement = "HOSTNAME={}\n".format(sys.argv[1]) 

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'): 
    if line.lstrip().startswith('HOSTNAME'): 
     line = replacement 
    sys.stdout.write(line) 

print 'Hostname set to {}'.format(sys.argv[1]) 

우리는 조건식을 사용하여 단 4이를 납작하게 할 수 있지만, 그 경우에 확실하지 않다 : 그것은 기본적으로 백업 파일을 만들어 지원 더 가독성있게 만듭니다.

for line in fileinput('/etc/sysconfig/network', inplace=True, backup='.setup_bak'): 
    sys.stdout.write(replacement if line.lstrip().startswith('HOSTNAME') else line) 
+0

두 번째'for' 루프는 지쳐있는 반복자를 반복하려고 시도하기 때문에 아무 것도하지 않습니다. (파일을 다시 반복하려면 첫 번째 루프 다음에'old_network.seek (0)'을 넣으십시오). –

+0

이 작업을 수행하는 데 약간의 문제가 있습니다. 어떤 이유로 든 line.lstrip(). startswith ('HOSTNAME') 문이 True를 반환하지 않습니다. 나는 파일에서 HOSTNAME = old_host를 가진 텍스트 파일을 시험해 보았고 위의 명령문을 참으로 반환하고 라인을 인쇄하지 않으면 그 라인을 인쇄하기 위해 루프를 만들었다. – numb3rs1x

+0

@ numb3rs1x :''HOSTNAME = foobarbaz \ n'.lstrip(). startswith ('HOSTNAME')'은 참을 반환합니다. –