2016-06-30 3 views
3

나는 다음과 같은 명령을 시도하고 좋은포트란 혼합 텍스트와 숫자

read (2,*) tempstr , my_param(1), tempstr , my_param(2), tempstr , my_param(3) 

문제는 언제 작동

number# 125 var1= 2 var2= 1 var3: 4 
     . 
     . 
     . 
     . 
number# 234 var1= 3 var2= 5 var3: 1 

다음과 같은 형식으로 데이터가 들어있는 파일을 읽을 포트란 90을 사용하고 읽기 다음과 같은 데이터가 보이는 즉, 숫자가 커지고 문자열과 숫자 사이에는 공백이 없습니다 :

number# 125 var1= 2 var2=124 var3: 4 

나는 내가 다른 언어로 전환 할 수 없습니다 제로

모든 숫자를 읽

 read (2,512) my_param(1), my_param(2), my_param(3) 

512 format('number#', i, 'var1=', i, 'var2=', i, 'var3:', i) 

을 시도했다. 데이터 세트가 너무 커서 전처리 할 수 ​​없습니다. 또한 구획 문자는 매번 동일하지 않습니다. 누군가 문제를 해결할 수 있습니까? 사전에

감사

+0

880.000MB, 720,000 라인 샘플 데이터에서 볼 수 있듯이 숫자 앞에는 "#", "="또는 ":"이 표시됩니다. 그것은 숫자 앞에 나타나는 것과 같은 상징이 아닙니다. –

+0

뭔가 제안 해 주시겠습니까? 어쩌면 샘플 코드 –

+0

샘플 데이터에서 볼 수 있듯이 숫자 앞에 "#", "="또는 ":"이옵니다. 그것은 숫자 앞에 나타나는 것과 같은 상징이 아닙니다. –

답변

2

나는 여전히 원래의 답변으로 서 있지만 입력 데이터가 이미 네임리스트 파일과 비슷하기 때문에 미리 데이터를 사전 처리 할 수 ​​없다고 가정 해 봅시다.

다음으로 가장 좋은 방법은 전체 라인을 character(len=<enough>) 변수로 읽은 다음 문자열 조작으로 그 값을 추출하는 것입니다. 다음과 같이 입력하십시오 :

program mixed2 
    implicit none 
    integer :: num, val1, val2, val3 
    character(len=50) :: line 
    integer :: io_stat 

    open(unit=100, file='data.dat', action='READ', status='OLD') 
    do 
     read(100, '(A)', iostat=io_stat) line 
     if (io_stat /= 0) exit 
     call get_values(line, num, val1, val2, val3) 
     print *, num, val1, val2, val3 
    end do 
    close(100) 

    contains 

     subroutine get_values(line, n, v1, v2, v3) 
      implicit none 
      character(len=*), intent(in) :: line 
      integer, intent(out) :: n, v1, v2, v3 
      integer :: idx 

      ! Search for "number#" 
      idx = index(line, 'number#') + len('number#') 

      ! Get the integer after that word 
      read(line(idx:idx+3), '(I4)') n 

      idx = index(line, 'var1') + len('var1=') 
      read(line(idx:idx+3), '(I4)') v1 

      idx = index(line, 'var2') + len('var3=') 
      read(line(idx:idx+3), '(I4)') v2 

      idx = index(line, 'var3') + len('var3:') 
      read(line(idx:idx+3), '(I4)') v3 
     end subroutine get_values 
end program mixed2 

오류/온 전성 검사를 포함하지 않았습니다. 나는 너에게 맡길거야.

+0

대단히 감사합니다 :) –

3

첫번째로, 사전 처리를 위해 너무 많이하지 720,000 라인. sedawk과 같은 도구는 대부분 줄 단위로 작동하므로 크기가 정말 좋습니다. 데이터가 올바르게 전처리 것을

$ cat preprocess.sed 

# Add commas between values 
# Space followed by letter -> insert comma 
s/ \([[:alpha:]]\)/ , \1/g 

# "number" is a key word in Fortran, so replace it with num 
s/number/num/g 

# Replace all possible data delimitors with the equals character 
s/[#:]/=/g 

# add the '&mydata' namelist descriptor to the beginning 
s/^/\&mydata /1 

# add the namelist closing "/" character to the end of the line: 
s,$,/,1 

$ sed -f preprocess.sed <data.dat> data.nml 

확인 :

$ tail -3 data.dat 
number#1997 var1=114 var2=130 var3:127 
number#1998 var1=164 var2=192 var3: 86 
number#1999 var1=101 var2= 48 var3:120 

$ tail -3 data.nml 
&mydata num=1997 , var1=114 , var2=130 , var3=127/ 
&mydata num=1998 , var1=164 , var2=192 , var3= 86/ 
&mydata num=1999 , var1=101 , var2= 48 , var3=120/ 

그럼 당신은 읽을 수 실제로 무슨 짓을

내가 namelists를 사용할 수있는 방식으로 데이터를 변환하는 것이 었습니다 이 포트란 프로그램과 함께 :

program read_mixed 
    implicit none 
    integer :: num, var1, var2, var3 
    integer :: io_stat 
    namelist /mydata/ num, var1, var2, var3 

    open(unit=100, file='data.nml', status='old', action='read') 
    do 
     read(100, nml=mydata, iostat=io_stat) 
     if (io_stat /= 0) exit 
     print *, num, var1, var2, var3 
    end do 
    close(100) 
end program read_mixed 
관련 문제