2014-02-28 1 views
0

파일 및 이름 (예 : "John")을 묻는 Python 스크립트를 작성하고 있습니다.문자열 찾기 및 다음 몇 줄 바꾸기

파일은 다음과 같은 라인의 전체 무리가 포함

... 
Name=John 
Age=30 
Pay=1000 
Married=1 
Name=Bob 
Age=25 
Pay=500 
Married=0 
Name=John 
Age=56 
Pay=3000 
Married=1 
... 

나는,이 파일을 열 이름의 사용자를 요청하고, 그 이름과 일치하는 모든 항목에 대해 지불 값을 대체합니다. 예를 들어, 사용자가 "John"을 입력하면 모든 "John"이 5000이되도록 지불을 변경하려고합니다. 다른 이름의 Pay 값은 변경되지 않습니다.

는 지금까지 내가 좀 더 쉽게 일 수 있도록 하나의 긴 문자열로 파일과 연결된 모든 것을 연 : 처음에는

for line in file: 
    file_string += line 

, 내가 문자열의 어떤 종류에 대해 생각을 대체하지만 didn를이 "John"을 검색 할 것이므로 "pan"을 제외하고 "John"을 바꾸고 싶지는 않지만 두 줄 아래의 Pay 값을 대신 사용하십시오.

대신 정규 표현식을 사용하기 시작했으며 이와 비슷한 것을 만들었습니다.

# non-greedy matching 
re.findall("Name=(.*?)\nAge=(.*?)\nPay=(.*?)\n", file_string, re.S) 

좋아요, 그래서 그 그룹의 3 튜플 목록을 뱉어 내고 모든 것이 잘된 것처럼 보입니다. 이제 실제 대체 할 ...

나는 ... 나는 그룹의 이름을 설정하고 나중에 그룹화 것을 사용할 수 있습니다 여기에 StackOverflow에 또 다른 질문에 읽기 :

re.sub(r'Name=(.*?)\nAge=(.*?)\nPay=', r'5000', file_string, re.S) 

나는 시도 모든 이름을 5000으로 바꾸고 작동하는지 확인하지만 그렇지 않습니다. 만약 그렇다면 아마 첫 번째 그룹이 사용자가 입력 한 이름과 일치하는지 확인해야 할 것입니다.

또 다른 문제는 re.sub이 가장 왼쪽 항목 만 대체한다는 Python 문서를 읽었습니다. 나는 모든 사건을 대체하고 싶다. 어떻게해야합니까?

이제 누군가가 나에게 도움이된다면 그렇게 할 수있는 일이 조금 손실됩니다.

+0

당신은 그냥 라인으로 파일 라인을 통해 이동하고 즉시 당신은 이름이 "존"에 도달로, 두 줄 아래로 지불 값을 변경 한 다음 읽기 나머지를 유지할 수 있습니다 윤곽. –

답변

2

그 정규식이 문제에 대한 최선의 해결책이라고 생각하지 않습니다. 나는보다 일반적인 해결책을 선호한다. 다른 대답은 다음 중 하나 이상에 달려 있습니다.

  1. 사람에게는 항상 4 개의 속성이 있습니다.
  2. 모든 사람마다 동일한 속성이 있습니다.
  3. 속성의 순서는 항상 같습니다.

위의 내용이 사실이라면 정규식이 될 수 있습니다.

내 솔루션이 더 자세한 정보이지만이 정보에 의존하지 않습니다.혼합/누락 속성, 혼합 주문을 처리하고 속성 값을 설정하고 가져올 수 있습니다. 당신은 조금이라도 확장 할 수 있고, 필요할 경우 새로운 재산이나 사람 삽입을 지원할 수 있습니다.

내 코드 :

# i omitted "data = your string" here 

def data_value(person_name, prop_name, new_value = None): 
    global data 
    start_person = data.find("Name=" + person_name + "\n") 
    while start_person != -1: 
     end_person = data.find("Name=", start_person + 1) 
     start_value = data.find(prop_name + "=", start_person, end_person)   
     if start_value != -1: 
      start_value += len(prop_name) + 1 
      end_value = data.find("\n", start_value, end_person) 
      if new_value == None: 
       return data[start_value:end_value] 
      else: 
       data = data[:start_value] + str(new_value) + data[end_value:]     
     start_person = data.find("Name=" + person_name + "\n", end_person) 
    return None 

print data_value("Mark", "Pay") # Output: None (missing person) 
print data_value("Bob", "Weight") # Output: None (missing property) 
print data_value("Bob", "Pay")  # Output: "500" (current value) 
data_value("Bob", "Pay", 1234)  # (change it) 
print data_value("Bob", "Pay")  # Output: "1234" (new value) 

data_value("John", "Pay", 555)  # (change it in both Johns) 
+0

이 솔루션을 사용 해줘서 고맙습니다. 실제로는 훨씬 강력하고 잘 작동하기 때문입니다. 자, 제가 물어보고 싶은 두 가지 이슈가 있습니다. 첫째로, 나는'string.find()'함수를 사용하는 것에 조금주의를 기울였다. 괜찮을거야? 둘째로, 나는이 기능이 '밥'의 한 가지 경우 만 변경한다고 생각한다. Bob의 모든 사건을 어떻게 Pay = 1234로 바꿀 수 있습니까? – noblerare

+0

첫 번째 :'find()'가 더 이상 사용되지 않을 것임을 나는 모른다. [python 3 str] (http://docs.python.org/3/library/stdtypes.html#str.find)에도 있습니다. 두 번째 : 나는 그것을하려고 노력하고, 당신에게 돌아 간다. – zord

+1

사람의 모든 출현을 바꿀 수 있도록 코드를 수정했다. "get"모드는 여전히 첫 번째 일치와 함께 반환됩니다. – zord

2

한 번에 4 줄 반복합니다. 첫 번째 줄에 'John'이 있으면 두 줄 뒤에 오는 줄을 편집하십시오.

data = """ 
Name=John 
Age=30 
Pay=1000 
Married=1 
Name=Bob 
Age=25 
Pay=500 
Married=0 
Name=John 
Age=56 
Pay=3000 
Married=1 
""" 

lines = data.split() 
for i, value in enumerate(zip(*[iter(lines)]*4)): 
    if 'John' in value[0]: 
     lines[i*4 + 2] = "Pay=5000" 

print '\n'.join(lines) 
1

다음 코드는 당신이 필요로 할 것입니다 :

import re 

text = """ 
Name=John 
Age=30 
Pay=1000 
Married=1 
Name=Bob 
Age=25 
Pay=500 
Married=0 
Name=John 
Age=56 
Pay=3000 
Married=1 
""" 

# the name you're looking for 
name = "John" 
# the new payment 
pay = 500 

print re.sub(r'Name={0}\nAge=(.+?)\nPay=(.+?)\n'.format(re.escape(name)), r'Name=\1\nAge=\2\nPay={0}\n'.format(pay), text) 
관련 문제