2016-06-30 9 views
3

私は、次のコマンドを試してみましたが、細かいFortranは混在テキストと数字

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 

次の形式でデータを含むファイルを読み込むためのFortran 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

まずアップ、72万ラインの前処理のためにも過言ではありません。 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/ 

次にあなたが読むことができますこのfortranプログラムで:

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 
関連する問題