使用vim、shell或python移动小数点
我有一个.pl文件,它由一个非结构化头和一些特定的X Y Z结构组成。标题中没有“.”。您可以在下面找到此文件的一个片段:使用vim、shell或python移动小数点,python,shell,vim,Python,Shell,Vim,我有一个.pl文件,它由一个非结构化头和一些特定的X Y Z结构组成。标题中没有“.”。您可以在下面找到此文件的一个片段: Header (in total 29 lines) ILINE VRTX 1 545057.78564453125 3800905.201171875 -15000 VRTX 2 545184.49072265625 3800765.451171875 -15000 VRTX 3 545310.91650390625 3800625.970703125 -15000
Header (in total 29 lines)
ILINE
VRTX 1 545057.78564453125 3800905.201171875 -15000
VRTX 2 545184.49072265625 3800765.451171875 -15000
VRTX 3 545310.91650390625 3800625.970703125 -15000
SEG 1 2
SEG 2 3
ILINE
VRTX 136 551295.84606933594 3799015.443359375 -15000
VRTX 137 551293.82849121094 3798841.880859375 -15000
VRTX 138 551290.57849121094 3798661.892578125 -15000
SEG 136 137
SEG 137 138
我想要实现的是将X和Y值的小数点向左移动,如下所示:
VRTX 1 5450.5778564453125 38009.05201171875 -15000
VRTX 2 5451.8449072265625 38007.65451171875 -15000
VRTX 3 5453.1091650390625 38006.25970703125 -15000
我认为正则表达式可能会有所帮助,但我没有使用Python或Shell的经验。感谢您的帮助
import re
new_data = ''
for line in data.splitlines():
if '.' in line:
mod_line = ''
for word in line.split():
if '.' in word:
try:
float(word)
word = re.sub(r'(\d\d)\.', r'.\1', word)
except:
pass
mod_line += word + ' '
new_data += mod_line.rstrip() +'\n'
else:
new_data += line + '\n'
new_data = new_data.rstrip()
print (new_data)
输出
ILINE
VRTX 1 5450.5778564453125 38009.05201171875 -15000
VRTX 2 5451.8449072265625 38007.65451171875 -15000
VRTX 3 5453.1091650390625 38006.25970703125 -15000
SEG 1 2
SEG 2 3
ILINE
VRTX 136 5512.9584606933594 37990.15443359375 -15000
VRTX 137 5512.9382849121094 37988.41880859375 -15000
VRTX 138 5512.9057849121094 37986.61892578125 -15000
SEG 136 137
SEG 137 138
这里有一个Python解决方案。首先,我们定义一个函数,为我们移动小数点
SEARCH = '.'
OFFSET = -2
def replacer(bits):
if SEARCH in bits:
loc = bits.index(SEARCH)+OFFSET
return ''.join('{}.'.format(x) if k == loc-1 else x for k,x in enumerate(bits.replace('.','')))
else:
return bits
接下来,将其应用于以下行:
s = """Header (in total 29 lines)
ILINE
VRTX 1 545057.78564453125 3800905.201171875 -15000
VRTX 2 545184.49072265625 3800765.451171875 -15000
VRTX 3 545310.91650390625 3800625.970703125 -15000
SEG 1 2
SEG 2 3
ILINE
VRTX 136 551295.84606933594 3799015.443359375 -15000
VRTX 137 551293.82849121094 3798841.880859375 -15000
VRTX 138 551290.57849121094 3798661.892578125 -15000
SEG 136 137
SEG 137 138"""
>>> for i in s.split('\n'):
.. if i.startswith('VRTX'):
.. print(' '.join(map(replacer, i.split(' '))))
VRTX 1 5450.5778564453125 38009.05201171875 -15000
VRTX 2 5451.8449072265625 38007.65451171875 -15000
VRTX 3 5453.1091650390625 38006.25970703125 -15000
VRTX 136 5512.9584606933594 37990.15443359375 -15000
VRTX 137 5512.9382849121094 37988.41880859375 -15000
VRTX 138 5512.9057849121094 37986.61892578125 -15000
您可以使用
awk
来执行此操作,这里有一行命令
awk '{for(i=1;i<=NF;i++)if(match($i,/[0-9][0-9]\./))$i=substr($i,0,RSTART-1)"."substr($i,RSTART,2)substr($i,RSTART+3)}1' input_file
awk'{for(i=1;i因为问题上有一个vim标签:
/\。
qanx2hi!@aq
@a
:%s/!//g
假设文本中没有!
,否则您必须用不同的字符替换它。当然,vim中还有其他解决方案,但这是我现在能想到的最简单的解决方案
细分:
/\”搜索文件中的每一个`.`
“(并将其“标记”为搜索结果)
qanx2hi!@aq“我们使用的宏:
qaq“将空宏记录到寄存器a中
“(这可确保登记册为空)
qa“这将再次开始将宏记录到寄存器a中
nx2hi!”`n`跳转到下一个搜索结果,
“`2hxhi!`插入一个`!`2个字符
“`.`已被删除,并退出插入模式
@a“调用寄存器'a'处的宏,因为我们清空了它,
“还没有发生任何事情,但一旦我们保存此宏,它就会发生。”
“在寄存器'a'中。因此它将调用自己,直到
达到中止条件(在
“文本,这就是为什么我们将`.`替换为`!`这里,其他
“宏会将`.`一次又一次地向左移动
q“停止录制宏并将其保存(以注册'a`)
@a“调用寄存器a中的宏`
:%s/!//g“这只是将文件中的所有”!`替换为“”`
可能的清洁剂解决方案:立即使用RAPScan(谢谢@Francesco)
/\。
:立即设置
qaqqax3hpn@aq
@a
:设置ws
注意:宏的顺序有点变化。我们必须先更改
的位置,然后跳到下一次搜索,否则我们将错过第一次搜索,因为搜索不再环绕eof
注意:最好先保存ws
的状态,然后再将其还原。但这只在通用版本中起作用
结论
复杂但灵活的解决方案。如果您不需要灵活,这里的其他vim解决方案更容易(我不会评判其他解决方案)一个复制粘贴友好的vim解决方案
:g/VRTX/normal f.xhhP;xhhP
说明:
- :g/{pattern}/command-在匹配模式的每一行上执行命令。在本例中,每一个VRTX行
- 正常-我们要执行的命令是正常模式命令
- f.-找到当前行中的第一个点
- xhhP-剪切该字符,向左移动两次,粘贴
- ;-查找下一个事件
- xhhP-再次移动点
我的正则表达式解决方案
:%s,\v(\d\d)\.,.\1,g
\v ...... very magic to avoid many backslashes
(\d\d) .. regex group one
\. ...... literal dot
\1 ...... reference to regex group one
你是否考虑以数字的形式阅读并乘以100?@ Yunnosch除以100@Yunnosch考虑到是的,但我不确定我该怎么做it@wizzwizz4你可能是对的。但是,用正则表达式移动小数点会失去同样的精度,至少在结果数字为e时是这样已计算。这当然是假设值最终在执行移动/乘法的相同环境中进行计算。此解决方案修改输入,您将丢失一位数的精度。现在应该修复。谢谢。它工作得很好。请您添加一些解释它的作用。当然,做了一些解释,只要问问你是否还有更多的问题,为什么不直接插入
而不是插入!
然后在末尾进行替换?nx2hP
vsnx2hi!
@PeterRincker,因为宏不会停止。n
将跳回顶部(到第一个
)然后再向左移动
。但是我可能会错过一些东西,因为我总是很高兴得到纠正/改进。我想简化宏方法的一个方法是禁用搜索包装。这也是我想到的一个很好的解决方案,但它只在同一行上的数字不超过两个的情况下起作用再次强调,这是最确定的情况,对于给定的用例,这使您的答案比我的更好!在我看来,这实际上是最好的vim解决方案。它真的很容易(应该考虑到这一点)。与francesco的解决方案一样,对
的数量没有限制。应该是公认的答案!