문제

입력이 형식의 ASCII 파일에 포함 된 실행 파일이 있습니다.

$ GENERAL INPUTS
$ PARAM1 = 123.456
PARAM2=456,789,101112
PARAM3(1)=123,456,789
PARAM4       =
1234,5678,91011E2
PARAM5(1,2)='STRING','STRING2'
$ NEW INSTANCE
NEW(1)=.TRUE.
PAR1=123
[More data here]
$ NEW INSTANCE
NEW(2)=.TRUE.
[etcetera]

다시 말해, 일부 일반적인 입력 및 다수의 새로운 인스턴스에 대한 일부 매개 변수 값. 매개 변수 선언은 불규칙합니다. 일부 숫자는 쉼표로 분리되고, 다른 숫자는 과학적 표기법이며, 다른 숫자는 인용문 내부에 있으며, 간격은 일정하지 않습니다.

일부 시나리오의 평가를 위해서는 하나의 "마스터"데이터 파일의 입력을 취하고 인스턴스 2에서 6의 매개 변수 데이터를 다른 데이터 파일에 복사해야합니다. 덮어 쓰기) 및 아마도 다른 사람 (변경되지 않은 데이터).

나는 Flex Lexer와 Bison Parser를 썼습니다. 함께 데이터 파일을 먹고 메모리에 매개 변수를 저장할 수 있습니다. 두 파일을 모두 열기 위해 사용하면 (마스터 및 "시나리오") 원하는 매개 변수를 세 번째 새 파일에 선택적으로 작성하는 것이 너무 어렵지 않아야합니다 ( "general input from 'scenario'; instances 1 though 5 from 'master'; instances 6 through 9 from 'scenario'; ..."), 저장하고 원래 시나리오 파일을 삭제하십시오.

기타 정보 : (1) 파일은 매우 민감합니다. 사용자가 마스터 파일을 변경하여 완전히 차폐하는 것이 매우 중요합니다. (2) 파일의 크기는 500k에서 10m 사이입니다.

나는 10 줄의 코드로 할 수있는 일을 배웠습니다. 여기서 일부 동료는 두 가지로 할 수 있습니다. 이 문제에 어떻게 접근 하시겠습니까? Pythonic 대답은 나를 울게 만들 것입니다. 진지하게.

도움이 되었습니까?

해결책

이미이 형식을 구문 분석 할 수 있다면 (Pyparsing을 사용하여 시도했지만 이미 작동하는 Flexx/Bison 솔루션이 있다면 괜찮을 것입니다). '기본적으로. 각 파일에서 읽은 내용을 "일반 입력"에 대한 DICT와 인스턴스 당 하나의 딕트 목록 (또는 인스턴스 덕트 인 인스턴스 숫자 일 수 있습니다. 좀 더 유연성을 제공하십시오). 그런 다음 언급했듯이 마스터에서 마스터에서 복사 한 인스턴스 중 일부를 선택적으로 "업데이트 또는 덮어 쓰기) 새 시나리오 파일을 작성하고 이전 파일을 대체하십시오.

Python과 함께 Flexx/Bison 코드를 사용하려면 몇 가지 옵션이 있습니다. DLL/SO로 만들어 CTYPES로 액세스하거나 Cython-Coded Extension, SWIG 래퍼, Python C-API Extension 또는 또는 Python C-API Extension에서 호출하십시오. 모금, 부스트 등

어떤 식 으로든 입력 파일 이름을 수용하고 해당 파일을 읽고 구문 분석하는 파서 프리미티브가 있다고 가정합니다. 각각은 다음 중 하나입니다.

  • (Paramname, Paramvalue)
  • ( '$$$$', '일반 입력')
  • ( '$$$$', '새 인스턴스')

'$$$$'를 일종의 임의의 마커로 사용합니다. 그런 다음 파일에서 읽은 모든 것을 나타내는 개체의 경우 다음과 같습니다.

import re

instidre = re.compile(r'NEW\((\d+)\)')

class Afile(object):

  def __init__(self, filename):
    self.filename = filename
    self.geninput = dict()
    self.instances = dict()

  def feed_data(self, listoftuples):
    it = iter(listoftuples)
    assert next(it) == ('$$$$', 'General Inputs')
    for name, value in it:
      if name == '$$$$': break
      self.geninput[name] = value
    else:  # no instances at all!
      return
    currinst = dict()
    for name, value in it:
      if name == '$$$$':
        self.finish_inst(currinst)
        currinst = dict()
        continue
      mo = instidre.match(name)
      if mo:
        assert value == '.TRUE.'
        name = '$$$INSTID$$$'
        value = mo.group(1)
      currinst[name] = value
    self.finish_inst(currinst)

  def finish_inst(self, adict):
    instid = dict.pop('$$$INSTID$$$')
    assert instid not in self.instances
    self.instances[instid] = adict

정신 점검은 약간 개선되어 이상이 이상을 더 정확하게 진단 할 수 있지만, 오류의 순수한 경우 이것이 당신이 원하는 대략이라고 생각합니다.

병합은 단지 수행하면됩니다 foo.instances[instid] = bar.instances[instid] 필요한 값의 경우 instid, 어디 foo 입니다 Afile 시나리오 파일의 인스턴스 bar 마스터 파일의 것입니다. 필요에 따라 덮어 쓰거나 추가합니다.

새로 변경된 시나리오 파일을 작성하려면 특정 입력을 반복 할 필요가 없다고 가정합니다. 특정 입력이 가질 수 있습니다 (그렇다면 이름과 가치와 함께 구문 분석 중에 그 기발한 것을 녹음해야합니다). , 단순히 반복 sorted(foo.instances) 정렬 된 순서로 각각을 쓰기 (일반적인 내용을 정렬 된 순서로 작성한 후, 적절한 $ this and that 마커 라인 및 적절한 번역 '$$$INSTID$$$' 진입 등) 충분해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top