gpt4 book ai didi

Perl命令根据位置替换字符串

转载 作者:行者123 更新时间:2023-12-02 09:26:49 26 4
gpt4 key购买 nike

我需要检查第 300 个字符是否是 { 。如果是,则需要将其替换为 0。还要考虑 { 之前的 10 位数字,生成一个负十进制数。示例:如果输入是 111123456789{ ,则输出将是 11-112345678.90
我的示例输入是:

H009704COV2009084    PHD0000001H009700204COV2009084    PROD2015122016010418371304COVH009704COV2009084    PTR0000001H0097002C00000000140000000043610000003408092A0000000068061C0000000000000{0000002939340H0000000537585H0000003476926F0000001218378G0000000040292E0000000016497{0000000000827E0000001880498{9000000320436J000000004391000000001606000000000030000000000128000000000006000000004227000000000000000000000000            00000140              0000000000000{0000000000773B0000000000000{000000000000
这里的第 300 个字符是 { 。因此,如果我将其替换为 0 并将其转换为负小数,则预期输出将为:
H009704COV2009084    PHD0000001H009700204COV2009084    PROD2015122016010418371304COVH009704COV2009084    PTR0000001H0097002C00000000140000000043610000003408092A0000000068061C0000000000000{0000002939340H0000000537585H0000003476926F0000001218378G0000000040292E0000000016497{0000000000827E000-000188049.809000000320436J000000004391000000001606000000000030000000000128000000000006000000004227000000000000000000000000            00000140              0000000000000{0000000000773B0000000000000{000000000000
我可以通过使用 sed 命令来做到这一点:
sed -e 's/\ (.\ {1,255\ }\ )\ (.\ {1,34\ }\ )\ (.\ {1,9\ }\ )\ ([^{]*\ ){/\1\2+\3.\40/'
但是当输入文件有大量记录(~80,000)时,性能很差。如何将上述 sed 命令转换为 Perl 以实现相同的功能?

最佳答案

一种方法是使用 Perl 中的 substr 函数。它通过偏移量(位置)和长度在另一个字符串中找到一个字符串。它可以选择用另一个参数替换它。它返回寻找的子串。
这里所需的转换有点复杂,所以它涉及 substr 的多次使用,以及一些计数。 - 需要向左插入 10 位,小数点/逗号需要向左插入 2 位。最后,{ 本身被替换。请注意,对于第一个字符,位置计数从 0 开始。
要了解这是如何工作的,请使用评论中的示例,即

111123456789{  -->  11-112345678.90

In this case { is at position 12.

echo "111123456789{" | perl -pe'
$x = substr($_, 2, 9); substr($_, 2, 9, "-$x."); substr($_, 14, 1, "0")'
(这需要复制粘贴或在终端的单行中输入;为了便于阅读,这里分成两行。)上面的 $_ 是 Perl 的“默认”变量,包含当前正在处理的内容,所以这里是输入字符串。这将按照指定打印 11-112345678.90
第一个命令提取位置之间的字符串,其中需要输入 -.,它从位置 12 左侧的 10 个位置开始(因此,在 2 处)并且长度为 9。然后将该子字符串写回那里,现在用 -. 填充。最后 { 替换为 0

subtstr 的另一种用法
虽然上面允许更一般的转换,对于插入字符的确切任务,可以简单地在给定位置添加 -.,通过使用 0 替换子字符串的长度。 { 的替换如上。
perl -pe 'substr($_, 2, 0, "-"); substr($_, 12, 0, "."); substr($_, 14, 1, "0")'
这样 $_ 每次都会改变,最后通过 -p 开关打印出来(见最后)。由于第一次插入添加了一个字符,因此第二次插入需要发生在字符串下方的一个位置。
请注意,这并不是更有效。虽然它避免创建新字符串 $x ,但它会额外更改一次字符串。重写字符串的任何部分,除了精确的字符替换,意味着至少必须保存字符串的其余部分,然后再复制回来。对于更长的字符串,这更昂贵,而且这种方法可能效率较低。但是,除非运行许多此类操作或在基准测试中,否则这不会引起注意。

要将其应用于实际问题,我们有 299 而不是 12:
perl -pe
'$x = substr($_, 289, 9); substr($_, 289, 9, "-$x."); substr($_, 301, 1, "0")'
input_file.txt
也可以使用上面的第二个示例,并适当调整数字。
Switches 和特殊变量:
  • -e 表示 '...' 里面的内容要被 Perl 作为程序执行
  • -p 遍历输入行并在每个输入行上运行 '' 中的程序。例如,这些行可能来自一个文件,如果在命令行上给出,它会自动打开并将行馈送到该程序。这就像 -n 一样,但是 -p 在程序处理完该行后也会打印 $_ (我们不需要说 print )
  • $_ , "the default input and pattern-searching space ,"具有当前输入行

  • 这也可以使用正则表达式来完成。见 the answer by PerlDuck

    注意
    从某种意义上说,上述程序是错误的,即使 { 不是寻找它的地方,它们也经历了所有处理,更改了字符串,问题中的显式条件是什么。
    相反,我们必须首先检查 { 是否确实在给定位置,然后执行上述操作。这显然很容易添加,但随后它变得更加笨拙和缓慢。相反,我更愿意推荐一个基于正则表达式的解决方案,比如 the answer by PerlDuck 中的解决方案。
    或者也许是一种更快的方式(如该答案下方所评论的)
    pos($string) = 290;
    $string =~ s/\G ([0-9]{9}) ([0-9]) \{ /-$1.${2}0/x;
    通过首先设置 pos \G assertion 将使正则表达式引擎在该位置启动。然后它分别匹配 9 和 1 位数字,然后是 { ,并根据需要替换它们。如果 { 不存在,则整个匹配失败并且字符串保持不变。

    关于Perl命令根据位置替换字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37206776/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com