Fortran Coder

查看: 19460|回复: 11

[输入输出] 如何在Fortran中实现像shell里的sed命令那样的文件内容替换

[复制链接]

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
发表于 2018-12-14 19:13:00 | 显示全部楼层 |阅读模式
简单点的,例如文件中的某行替换成某一个字符串
稍微难一点的,例如文件中的某些字符替换成某一个字符串
再复杂一点的,例如文件中符合条件的某些行进行特定替换操作或者类似于shell中awk那样的表控操作
其实吧,自行编写特定的Fortran子程序,对只有一行的文件都可以做到
但是Fortran似乎一旦只要写文件,就得从头到尾地写,没法实现Shell那样的中间替换
我曾试想过用Call System("")的语句,“”中是shell命令
这个问题是一次只能写一行,太复杂的shell命令实现不了
更大的问题是这样无法实现shell和Fortran的数据传递,这才是更要命的
各位大神,请问有什么办法没有……

953

帖子

0

主题

0

精华

大师

F 币
180 元
贡献
73 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
发表于 2018-12-14 22:19:36 | 显示全部楼层
其实Shell也只能从头到尾地写。但是这些解释型脚本,做了一些封装,使得一个复杂的过程被简单的一个语句代替了而已。
Fortran中你也可以这样,全部读入内存里,在内存里处理、替换、然后决定要保存的时候,再全部写入文件。

此外,你可以把多个Shell语句先写入 .sh 文件,然后 call system 让操作系统执行这个 .sh 脚本。

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
 楼主| 发表于 2018-12-14 22:39:40 | 显示全部楼层
vvt 发表于 2018-12-14 22:19
其实Shell也只能从头到尾地写。但是这些解释型脚本,做了一些封装,使得一个复杂的过程被简单的一个语句代 ...

哈,您这么说我感觉恍然大悟啊
可是还是解决不了一个问题啊,把一个文件全部读入内存,这个操作感觉很扯着蛋啊……
怎么弄呢……
定义一个数据成员是待定长度字符串的派生类型,然后建立一个这样的链表?
不管怎样,这都是一个很耗内存的事情啊,文件多大至少就要耗多大内存呢……
另外,您说的用sh文件在Fortran内执行复杂shell命令确实很有启发
不过,这个还是解决不了shell和Fortran互相传递数据不便的问题,这个有好办法么?
我用建立文件的办法实现过,不过这不是什么好办法,文件I/O是很没有效率的一件事情……
如果想同时利用shell脚本处理文字方便和Fortran数据处理强的优势,这样的互传数据又是很重要的

953

帖子

0

主题

0

精华

大师

F 币
180 元
贡献
73 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
发表于 2018-12-15 10:33:43 | 显示全部楼层
说真的,Fortran的文本处理能力的确不怎么样。
你用Shell处理大文件也一样的消耗内存的。并没有什么本质区别。

我对文本处理没有太大的需求,所以了解也不多。
大量的数据互传,没有什么好的思路。

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
 楼主| 发表于 2018-12-15 11:10:40 | 显示全部楼层
vvt 发表于 2018-12-15 10:33
说真的,Fortran的文本处理能力的确不怎么样。
你用Shell处理大文件也一样的消耗内存的。并没有什么本质区 ...

一样耗内存啊,我还以为shell的脚本有什么优化方法能减少内存消耗呢
既然如此,用Fortran给自己写一些类似于sed,awk,head,tail之类的封装至成熟也是可行啊
不过这个有点耗时间,对于一些小问题可能还是想用shell和Fortran混合编程了

至于对于数据互传,看来我的表述方式有问题,让大佬你误解了
我倒不是说能有什么大量数据的互传
就是说有没有什么办法在用Shell和Fortran混合编写的时候,
在内存里两种程序语言间互传数据,目前我是先把数据写到文件里再用另外一种语言去读
这样的文件I/O据说速度很低,应该尽量避免啊,希望能有类似于shell里的管道的方式

举个例子,比如某个文件里我希望读取最后一行第二个空格后的数据
然后接下来这个数据要用于Fortran计算
从文字处理上,直接用shell里的awk命令显然是最省心的
可是问题是用shell读出来了,Fortran程序里却是没有这个数据的,哪怕作为字符串也没有
那么有没有不用文件I/O的方法把这个数据或者字符串传递给Fortran程序呢
当然,大佬你之前说的很对,这个功能可以自己写一个Fortran子程序在Fortran内部实现
但是如果大量涉及到类似的东西的话,就除非自己写一个函数库了
所以我就像问下,如果采用shell和Fortran混合编程结合优势的话有没有什么好办法实现这种数据互传

另外,我不太了解C,是不是C的库里也有类似于sed,awk,head,tail等这样方便的文字处理函数
如果有的话,是不是用C/Fortran混合编程是不是比较容易解决数据互传的问题……

1948

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1298 元
贡献
547 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2018-12-15 11:30:11 | 显示全部楼层
管道当然可以呀
QQ截图20181215112933.png

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
 楼主| 发表于 2018-12-15 12:48:28 | 显示全部楼层
fcode 发表于 2018-12-15 11:30
管道当然可以呀

哈,谢谢版主,好有趣的功能,非常有启发性
这确实是把通过shell管道得到数据作为Fortran程序的输入了唉
不过还是和我预想的功能有些不太一样,应该还是我描述的不完整
实际上我的程序可能会有shell何Fortran程序来回互传数据啊
唉,还不如完整说下我的问题吧
我其实是想用Fortran写一个vasp用的脚本
实现的功能是多次调用vasp进行计算,根据每次计算得到的能量调整输入的POSCAR文件
在这里,每次从vasp的结果文件中读入能量和改写POSCAR文件都是用Shell文字处理比较方便的
但是对于根据得到的能量进行优化计算,这些都是用Fortran更合适
所以需要做的流程实际上是:
调用vasp(shell)->读入vasp输出文件中的能量(shell)->计算得到优化结构(Fortran)->改写vasp输入文件POSCAR(shell)->调用vasp(shell)
这样的循环,所以需要来回在shell和Fortran中互传数据
我试想了一下,版主这种方式似乎只有在读入能量给Fortran中这一步是好用的
如果互传数据只有这一步应该是可以用的,可惜不仅仅是啊

1948

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1298 元
贡献
547 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

发表于 2018-12-15 13:02:36 | 显示全部楼层
你可以通过Shell循环,然后把fortran 输出 write 的内容通过管道接收到,保存到内存里。
然后进行下一次循环。

这是没有问题的,我们也经常利用这种方法来做迭代。

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
 楼主| 发表于 2018-12-15 13:07:52 | 显示全部楼层
fcode 发表于 2018-12-15 13:02
你可以通过Shell循环,然后把fortran 输出 write 的内容通过管道接收到,保存到内存里。
然后进行下一次循 ...

非常感谢
你是指Fortran写的执行程序只运行一次
但是在Shell脚本里在多个管道里使用它,直到完成任务为止?

178

帖子

15

主题

0

精华

大宗师

F 币
4973 元
贡献
1152 点
 楼主| 发表于 2018-12-15 14:32:53 | 显示全部楼层
fcode 发表于 2018-12-15 13:02
你可以通过Shell循环,然后把fortran 输出 write 的内容通过管道接收到,保存到内存里。
然后进行下一次循 ...

再想想,我知道了,你的意思是管道还可以继续往下接
不过怎么用循环来做迭代就想不出来了,要是版主能好心给个简单的例子就好了……
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-3-29 13:59

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表