簡體   English   中英

如何使用 Perl 搜索和修改文件中字符串后面的浮動值

[英]How to search and modify floating values that follow a string in a file using Perl

假設我們在一個文件中多次出現“abc {{1.1 2.2}}”,我想將其修改為“xyz {{2.2 4.4}}”,這基本上是:

  • 將 abc 更改為 xyz。
  • 並將浮點值乘以 2 出現在花括號中(始終以 abc 關鍵字開頭)。
abc {{1.1 2.2}} ----------> xyz {{2.2 4.4}}

必須對文件的所有實例進行此修改。 這是我嘗試過的代碼,但只能將 abc 替換為 xyz 並且無法弄清楚如何通過提取這些浮點值來進行操作。

#!/usr/bin/perl -w

use strict;

open(FILE, "</tmp/yourfile.txt") || die "File not found";
my @lines = <FILE>;
close(FILE);

foreach(@lines) {
   $_ =~ s/abc/xyz/g;
}

open(FILE, ">/tmp/yourfile.txt") || die "File not found";
print FILE @lines;
close(FILE);

任何形式的幫助都受到高度贊賞。

我認為您希望保留小數位數(和/或控制它),並且可能需要以比單純*2更復雜的方式來操作浮點數

perl -wE' $_=q(abc {{0.2 14.55}}); 
    say; 
    s{ abc \s+ \{\s*\{\s* \K  
       ([0-9]+\.([0-9]+)) (\s+) ([0-9]+\.([0-9]+))  (?=\s*\}\s*\})
    }{
       ($l2,$l5) = map length, $2, $5; 
       sprintf("%.${l2}f", 2*$1) .$3. sprintf("%.${l5}f", 2*$4)
    }ex; 
    say'

這提出了一些基本假設。 它打印

abc {{0.2 14.55}}
abc {{0.4 29.10}}

注釋

  • \\K使它放棄所有匹配到該點; 它們不需要被捕獲並重新輸入作為替代品,因為它們沒有被“消耗”。 所以我們匹配第一部分並不管它

  • }e修飾符使其將替換端評估為 Perl 代碼。 在那里我們格式化乘以原始小數位數所得的數字

  • 匹配部分末尾的位(?=...)前瞻

  • 如果數字可能帶有-/+則需要將這些字符添加到模式中

    ([-+]?[0-9]+\\.([0-9]+))

    如果該+需要在輸出中重現,那么您還需要捕獲符號([-+]?) ,以便能夠檢查替換側並添加它(如果它在那里)。

OP 未提供輸入文件樣本,因此以下代碼可能無法反映正確的解決方案。

假設模式abc {{xx xx}}不會在行上出現多次。

use strict;
use warnings;
use feature 'say';

my $debug = 0;

for (<DATA>) {
    chomp;
    say $_ if $debug;
    if( /(.*)?abc\s*\{\{\s*([\d\.]+)\s*([\d\.]+)\s*\}\}(.*)/ ) {
        my($a,$b) = ($2,$3);
        $a *= 2;
        $b *= 2;
        say $1 . "xyz {{$a $b}}" . $4;
    } else {
        say $_;
    }
}

__DATA__
This an example data abc {{1.1 2.2}} which required some manipulation.

We should take abc {{1.1 2.2}} and replace 'abc' to 'xyz' take two
float numbers in curly brackets and multiply each by 2, write result
as xyz {{2.2 4.4}}.

Let's play with some numbers
        abc {{7.2 12.4}}
            boy {{0.5 8.2}}
        put {{2.3 8.6}}
            got {{4.1 2.3}}
        abc {{0.5 4.9}}

Note: numbers can have values different from provided sample

輸出

This an example data xyz {{2.2 4.4}} which required some manipulation.

We should take xyz {{2.2 4.4}} and replace 'abc' to 'xyz' take two
float numbers in curly brackets and multiply each by 2, write result
as xyz {{2.2 4.4}}.

Let's play with some numbers
                xyz {{14.4 24.8}}
                        boy {{0.5 8.2}}
                put {{2.3 8.6}}
                        got {{4.1 2.3}}
                xyz {{1 9.8}}

Note: numbers can have values different from provided sample

我的 Perl 正則表達式生銹了,但這樣的事情應該會有所幫助:

use Test::More tests => 6;

sub match_and_replace
{
    $_[0] =~ /abc \{\{([+-]?([0-9]*[.])?[0-9]+) ([+-]?([0-9]*[.])?[0-9]+)}}/;
    my $my1 = $1*2;
    my $my3 = $3*2;
    my $ret = $_[0];
    $ret =~ s/abc \{\{$1 $3}}/xyz \{\{$my1 $my3}}/g;
    return $ret;
}

is(match_and_replace('abc {{1.1 2.2}}'), 'xyz {{2.2 4.4}}', 'simple float');
is(match_and_replace('abc {{12.12 23.23}}'), 'xyz {{24.24 46.46}}', 'bigger float');
is(match_and_replace('abc {{1.99 99.1}}'), 'xyz {{3.98 198.2}}', 'another float');
is(match_and_replace('abc {{.5 .5}}'), 'xyz {{1 1}}', 'only fractional part');
is(match_and_replace('abc {{2 6}}'), 'xyz {{4 12}}', 'only integer part');
is(match_and_replace('abc'), 'abc', 'no match');

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM