Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.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
Perl 从复杂括号系统中提取字符串_Perl - Fatal编程技术网

Perl 从复杂括号系统中提取字符串

Perl 从复杂括号系统中提取字符串,perl,Perl,我有一个字符串如下所示: (((Q,(P,(O,(M,N)))),(B,A)),C) 1|MN 2|MNO 3|MNOP 4|MNOPQ 5|BA 6|MNOPQBA 7|MNOPQBAC 我想把这封信放在括号里如下: (((Q,(P,(O,(M,N)))),(B,A)),C) 1|MN 2|MNO 3|MNOP 4|MNOPQ 5|BA 6|MNOPQBA 7|MNOPQBAC 我该怎么做?我是编程新手,开始用Perl编写代码,如有任何帮助,将不胜感激。谢谢 编写一个简单的解析器: s

我有一个字符串如下所示:

(((Q,(P,(O,(M,N)))),(B,A)),C)
1|MN
2|MNO
3|MNOP
4|MNOPQ
5|BA
6|MNOPQBA
7|MNOPQBAC
我想把这封信放在括号里如下:

(((Q,(P,(O,(M,N)))),(B,A)),C)
1|MN
2|MNO
3|MNOP
4|MNOPQ
5|BA
6|MNOPQBA
7|MNOPQBAC
我该怎么做?我是编程新手,开始用Perl编写代码,如有任何帮助,将不胜感激。谢谢

编写一个简单的解析器:

sub parse {
  my ($string_ref) = @_;

  # check if the remaining string is a (x,y) group
  if ($$string_ref =~ s/\A[(]//) {
    my $first = parse($string_ref);
    $$string_ref =~ s/\A[,]// or die "Expected a comma [,]";
    my $second = parse($string_ref);
    $$string_ref =~ s/\A[)]// or die "Expected a closing paren [)]";
    return [$first, $second];
  }
  # check if we have a simple string
  elsif ($$string_ref =~ s/\A([^,()]+)//) {
    return $1;
  }
  else {
    die "Expected [(] or [^,()]";
  }
}
这是一个为嵌套零件调用自身的子例程。它接受对字符串的引用。要获取该引用中的字符串,我们必须取消对它的引用:
$$reference
。要创建引用,我们使用
\
操作符:
$reference=\$value

=~s/../…/
将替换应用于字符串。在模式中,
\A
固定在字符串的开头,而
[…]
是一个字符类。因为替换的第二部分是空的,所以字符串开头的匹配部分被删除

现在
my$str=“((Q,(p,(O,(M,N))),(B,A)),C)”;parse(\$str)
生成此数据结构:

[[["Q", ["P", ["O", ["M", "N"]]]], ["B", "A"]], "C"]
下一个问题是将此数据结构展平到字符串中。同样,我们可以编写一个递归解决方案,因为整平整个数据结构与整平此数据结构的一部分是相同的过程

sub flatten {
  my ($data) = @_;

  if (ref $data eq 'ARRAY') {
    my ($first, $second) = @$data;
    my ($first_str,  @first_others ) = flatten($first );
    my ($second_str, @second_others) = flatten($second);
    my $str = $first_str . $second_str;
    my @others = (@first_others, @second_others, $str);
    return $str, @others;
  }
  elsif (ref $data eq '') {
    return $data;
  }
  else {
    die "Unknown data type ", ref $data;
  }
}
ref
内置函数返回引用的类型。如果结果是空字符串,则该值不是引用(在本例中,它将是普通字符串)。上面的代码大量使用了列表分配:
($x,@y)=(1,2,3)
分配数字,以便
$x=1
@y=(2,3)
。这也适用于数字较少的情况–如果
($x,@y)=(1)
,则
@y
将为空。还请注意,我们返回单个值(当展平字符串时)或多个值(当展平参数的内容时)

应用于该数据结构,我们得到以下列表:

(
  "QPOMNBAC",
  "MN",
  "OMN",
  "POMN",
  "QPOMN",
  "BA",
  "QPOMNBA",
  "QPOMNBAC",
)
那么我们怎样才能得到你想要的输出呢

use feature 'say';

my ($whole_string, @parts) = flatten(parse(\$str));

for my $i (0 .. $#parts) {
  say $i + 1, "|", $parts[$i];
}
产生

1|MN
2|OMN
3|POMN
4|QPOMN
5|BA
6|QPOMNBA
7|QPOMNBAC
字符串中的顺序与所需的不同–您似乎已按字母顺序对每个paren中的部分进行了排序。为此,我们必须更改
flatten
中的某些内容。但是,如果不知道要如何准确排序,这是不可能做到的。

编写一个简单的解析器:

sub parse {
  my ($string_ref) = @_;

  # check if the remaining string is a (x,y) group
  if ($$string_ref =~ s/\A[(]//) {
    my $first = parse($string_ref);
    $$string_ref =~ s/\A[,]// or die "Expected a comma [,]";
    my $second = parse($string_ref);
    $$string_ref =~ s/\A[)]// or die "Expected a closing paren [)]";
    return [$first, $second];
  }
  # check if we have a simple string
  elsif ($$string_ref =~ s/\A([^,()]+)//) {
    return $1;
  }
  else {
    die "Expected [(] or [^,()]";
  }
}
这是一个为嵌套零件调用自身的子例程。它接受对字符串的引用。要获取该引用中的字符串,我们必须取消对它的引用:
$$reference
。要创建引用,我们使用
\
操作符:
$reference=\$value

=~s/../…/
将替换应用于字符串。在模式中,
\A
固定在字符串的开头,而
[…]
是一个字符类。因为替换的第二部分是空的,所以字符串开头的匹配部分被删除

现在
my$str=“((Q,(p,(O,(M,N))),(B,A)),C)”;parse(\$str)
生成此数据结构:

[[["Q", ["P", ["O", ["M", "N"]]]], ["B", "A"]], "C"]
下一个问题是将此数据结构展平到字符串中。同样,我们可以编写一个递归解决方案,因为整平整个数据结构与整平此数据结构的一部分是相同的过程

sub flatten {
  my ($data) = @_;

  if (ref $data eq 'ARRAY') {
    my ($first, $second) = @$data;
    my ($first_str,  @first_others ) = flatten($first );
    my ($second_str, @second_others) = flatten($second);
    my $str = $first_str . $second_str;
    my @others = (@first_others, @second_others, $str);
    return $str, @others;
  }
  elsif (ref $data eq '') {
    return $data;
  }
  else {
    die "Unknown data type ", ref $data;
  }
}
ref
内置函数返回引用的类型。如果结果是空字符串,则该值不是引用(在本例中,它将是普通字符串)。上面的代码大量使用了列表分配:
($x,@y)=(1,2,3)
分配数字,以便
$x=1
@y=(2,3)
。这也适用于数字较少的情况–如果
($x,@y)=(1)
,则
@y
将为空。还请注意,我们返回单个值(当展平字符串时)或多个值(当展平参数的内容时)

应用于该数据结构,我们得到以下列表:

(
  "QPOMNBAC",
  "MN",
  "OMN",
  "POMN",
  "QPOMN",
  "BA",
  "QPOMNBA",
  "QPOMNBAC",
)
那么我们怎样才能得到你想要的输出呢

use feature 'say';

my ($whole_string, @parts) = flatten(parse(\$str));

for my $i (0 .. $#parts) {
  say $i + 1, "|", $parts[$i];
}
产生

1|MN
2|OMN
3|POMN
4|QPOMN
5|BA
6|QPOMNBA
7|QPOMNBAC

字符串中的顺序与所需的不同–您似乎已按字母顺序对每个paren中的部分进行了排序。为此,我们必须更改
flatten
中的某些内容。但是,如果不知道要如何准确排序,这是不可能的。

删除逗号并将结果作为参数提供给任何(大部分)lisp:)的读取函数。

删除逗号并将结果作为参数提供给任何(大部分)lisp:)的读取函数。

欢迎使用堆栈溢出!请花点时间阅读文档。虽然您的问题是关于编程的,但它要求我们完全解决您的问题。它看起来也很像家庭作业。家庭作业没什么问题,但你应该自己想想。通过让别人解决问题来作弊会在以后伤害到你。请花点时间考虑一下如何做到这一点。只要考虑一种方法/算法,如果不能在Perl中实现,就把它写下来。我们感谢这里的努力。:)欢迎来到堆栈溢出!请花点时间阅读文档。虽然您的问题是关于编程的,但它要求我们完全解决您的问题。它看起来也很像家庭作业。家庭作业没什么问题,但你应该自己想想。通过让别人解决问题来作弊会在以后伤害到你。请花点时间考虑一下如何做到这一点。只要考虑一种方法/算法,如果不能在Perl中实现,就把它写下来。我们感谢这里的努力。:)简洁的解释!“你今年要来吗?”辛巴基,谢谢。我不太确定我是否会去,但我当然想来。注册什么时候结束?请给我发邮件到meine hannover.pm地址。非常感谢!!字符串内部的顺序并不重要,真的很感谢。你太棒了,你能不能再设计一些,什么时候()被[]替换了?简洁的解释!你要来吗