【问题标题】:How do I do a search in Perl?如何在 Perl 中进行搜索?
【发布时间】:2021-12-13 22:27:06
【问题描述】:

我有问题。 我试图在 Perl 中处理规范化。

假设我有以下两个 key.txt 和 value.txt 输入文件。 比如第一行key.txtunix_socket_connect对应value.txtallow $1 $2_socket:sock_file write;allow $1 $3:unix_stream_socket connectto;

key.txt:

unix_socket_connect
set_prop
get_prop
unix_socket_send

value.txt:

allow $1 $2_socket:sock_file write;allow $1 $3:unix_stream_socket connectto;
unix_socket_connect($1, property, init)allow $1 $2:property_service set;get_prop($1, $2)
allow $1 $2:file { getattr open read map };
allow $1 $2_socket:sock_file write;allow $1 $3:unix_dgram_socket sendto;

result.txt:

unix_socket_connect , allow $1 $2_socket:sock_file write;allow $1 $3:unix_stream_socket connectto;
set_prop , allow $1 property_socket:sock_file write;allow $1 init:unix_stream_socket connectto;allow $1 $2:property_service set;allow $1 $2:file { getattr open read map };
get_prop , allow $1 $2:file { getattr open read map };
unix_socket_send , allow $1 $2_socket:sock_file write;allow $1 $3:unix_dgram_socket sendto;

如果键存在于值的内容中,这些用于重写值。

这就像扩展一个函数。这里,第二行包含第一行和第三行的值。

说明一下,如果值中写入unix_socket_connect,则参数会按照$1$2$3的顺序反映,然后

"unix_socket_connect($1, property, init)

unix_socket_connect($1, property, init) → allow $1 property_socket:sock_file write;allow $1 init:unix_stream_socket connectto;

为此,我想出了以下代码。

#!/usr/bin/env perl
use strict;
use warnings;

my $key_file = 'key.txt';
my $value_file = 'value.txt';
my $result_file = 'result.txt';

my @key = ();
my @value = ();

# input text
open(KEY, "$key_file");
while(<KEY>){
    push @key ,$_;
}

open(VALUE, "$value_file");
while(<VALUE>){
    push @value ,$_;
}


for(my $i=0; $i < $#value+1; $i++){
    for(my $j = 0; $j < $#key+1; $j++){
       if($value[$i] =~ /$key[$j]/){
           $value[$i] = $value[$j];
       }
    }
}


open (RESULT, "> $result_file") or die "$!";
 for(my $i = 0; $i < $#value+1; $i++){
    print OUT "$key[$i]" . " ," . "$value[$i]";
}


close(KEY);
close(VALUE);
close(RESULT);

但是,我没有得到我想要的输出,我没有正确比较键和值吗?

【问题讨论】:

  • 如果你运行它,什么都不会被替换并且输出会是一样的。
  • 解决 chomp 问题后,您可能需要$value[$i] =~ s/$key[$j]/$value[$j]/ 之类的东西,而不是替换整行。

标签: perl


【解决方案1】:

我理解的问题

你想扩展

unix_socket_connect($1, property, init)

allow $1 property_socket:sock_file write;allow $1 init:unix_stream_socket connectto;

给定的定义,例如

my %defs = (
   unix_socket_connect => 'allow $1 $2_socket:sock_file write;allow $1 $3:unix_stream_socket connectto;',
   ...
);

解决方案

假设我们达到了我们所拥有的地步

my $name = 'unix_socket_connect';
my $def  = 'allow $1 $2_socket:sock_file write;allow $1 $3:unix_stream_socket connectto;'
my @args = ( '$1', 'property', 'init' );

$def 实际上是一个简单的模板。我们可以使用替换来解决这个问题。

s{
   \$(\d+)
}{
   my $i = $1 - 1;
   0 <= $i && $i < @args ? $args[$i] : $&
}xeg;

所以现在我们需要找到子调用。该语言似乎不支持嵌套调用(例如unix_socket_connect(..., getprop(...), ...)),这使得这相当容易。

s{
   \b (\w+) \b \( ([^()]+) \)
}{
   my $name = $1;
   my @args = split /\s*,\s*/, $2;

   if (defined( my $def = $defs{$name} )) {
      $def =~ s{
         \$(\d+)
      }{
         my $i = $1 - 1;
         0 <= $i && $i < @args ? $args[$i] : $&
      }xegr
   } else {
      $&
   }
}xeg;

【讨论】:

    猜你喜欢
    • 2017-01-05
    • 2011-07-16
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 2014-07-02
    • 2010-10-29
    • 1970-01-01
    • 2016-05-28
    相关资源
    最近更新 更多