Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用vim、shell或python移动小数点_Python_Shell_Vim - Fatal编程技术网

使用vim、shell或python移动小数点

使用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

我有一个.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 
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
      vs
      nx2hi!
      @PeterRincker,因为宏不会停止。
      n
      将跳回顶部(到第一个
      )然后再向左移动
      。但是我可能会错过一些东西,因为我总是很高兴得到纠正/改进。我想简化宏方法的一个方法是禁用搜索包装。这也是我想到的一个很好的解决方案,但它只在同一行上的数字不超过两个的情况下起作用再次强调,这是最确定的情况,对于给定的用例,这使您的答案比我的更好!在我看来,这实际上是最好的vim解决方案。它真的很容易(应该考虑到这一点)。与francesco的解决方案一样,对
      的数量没有限制。应该是公认的答案!