3

似たような質問がありますが、これは少し違うと思います。

基本的に、次の文字列があるとします。

" aa{bb{dccd"

ここで、最後のブレースで文字列を分割したいと思い{ます。パーツを配列として返します。次を使用して、この文字の位置 (0 ベースのインデックス) を簡単に見つけることができますrindex

perl -e '
$aa="aa{bb{dccd" ;
$ri = rindex($aa, "{") ;
print "$ri\n"; '

5

...そして、私がPerlコーダーではないことを考えると、最初に考えるのは、のようなものを使用することです$str = split($aa, 3). 残念ながら、これは正しい構文ではありませんsplit。正規表現を最初の引数 (照合するもの) として取り、文字列を 2 番目の引数として取ります。また、整数の位置インデックスを引数として取りません。

Perl Guru Forums: Perl Programming Help: I​​ntermediate: split or splice string on char count?のような投稿を見つけました。substr、同様のコンテキストでの使用を推奨しています。ただし、substr上記の例のように、リストに入力するには 2 つの s を記述する必要があるため、substr の代替案について聞きたいと思います。

基本的に、N番目の文字の位置を一致させる問題が正規表現の一致として表現できる場合、splitそれも同様に機能する可能性があります-それが私の主な質問です. ただし、文字位置を指定する整数のリスト/配列を受け入れ、分割されたセクションを含む配列を返す Perl 組み込み関数があるかどうかも知りたいです。

編集:

上記を要約すると、デバッグ用に印刷したいので、文字インデックスが必要です。同時に、文字列を配列に分割するためにそれらを使用しますが、substrs は使用しません。

EDIT2:OPから何かを省略したことに気づきました-つまり、私が取り組んでいる問題では、最初に文字インデックスを取得する必要があります(rindexまたはその他の方法で); 次に、それらに対して計算を行う必要があります (そのため、増加または減少する可能性があります)。その場合にのみ、(新しいインデックス値に基づいて) 文字列を分割する必要があります。私の元の例が単純すぎて、インデックス/文字位置に焦点を当てていることをあまり表現していなかったのかもしれません (そして、最初に考えたのはsplitとにかく文字インデックスを暗示していることは言うまでもありませんが、それがどのプログラミング言語だったか思い出せません)。から:)

4

6 に答える 6

3
my ($pre, $post) = split /\{(?!.*\{)/s, $s;

また

my ($pre, $post) = $s =~ /^(.*)\{(.*)/s;

2 番目のほうがよいでしょう。

のインデックスが必要な場合は{、 を使用しますlength($pre)。(2 番目の解決策では、 も使用できます。 perlvarのandを$-[2] - 1参照してください。)@-@+

于 2012-06-08T19:42:49.737 に答える
3

あなたが書いた:

また、文字位置を指定する整数のリスト/配列を受け入れ、分割されたセクションを含む配列を返す Perl 組み込み関数があるかどうかも知りたいです。

オフセットのリストを取り、それらの分割位置を持つ部分文字列のリストを生成する関数を作成するには、オフセットを長さに変換し、引数として に渡しますunpack

Perl Cookbookの第 1 章に、まさにこれを行う&cut2fmt関数があります。以下は抜粋であり、著者の親切な許可を得てここに転載します。

データを特定の列で切り取ったものと考えたい場合があります。たとえば、位置 8、14、20、26、および 30 の直前にカットを配置したい場合があります。これらは、各フィールドが始まる列番号です。unpack適切な形式はであると計算できますが"A7 A6 A6 A6 A4 A*"、これは高潔で怠惰な Perl プログラマーにとって精神的な負担が大きすぎます。Perl に理解させてください。cut2fmt以下の関数を使用します。

sub cut2fmt {
      my(@positions) = @_;
      my $template   = '';
      my $lastpos    = 1;
      foreach $place (@positions) {
          $template .= "A" . ($place - $lastpos) . " ";
          $lastpos   = $place;
      }
      $template .= "A*";
      return $template;
  }

  $fmt = cut2fmt(8, 14, 20, 26, 30);
  print "$fmt\n";

  A7 A6 A6 A6 A4 A*

したがって、それを使用する方法は次のようになります。

$fmt = cut2fmt(8, 14, 20, 26, 30);
@list = unpack($fmt, $string);

または直接

@list = unpack(cut2fmt(8, 14, 20, 26, 30), $string);

これがあなたが求めていたものだと思います。

于 2012-06-08T19:53:51.657 に答える
2

以下にいくつかの方法を示します。

split /.*\K{/, $str;
split /{(?!.*{)/, $str;
$str =~ /(.*){(.*)/;

/regex/s文字列が複数行にまたがる場合に使用します。

于 2012-06-08T19:42:42.580 に答える
1

何がそんなに難しいのか、いまだにわかりません。ブレース(または区切り文字が何であれ)を破棄したくないということですか?@Qtax のソリューションのこれらの適応は、最初または 2 番目の部分文字列に中括弧を残します。

# split before the brace
split /.*\K(?=\{)/, $str;
split /(?=\{(?!.*\{))/, $str;
$str =~ /(.*)(\{.*)/;

# split after the brace
split /.*\{\K)/, $str;
split /(?<=\{(?!.*\{))/, $str;
$str =~ /(.*\{)(.*)/;

(ブレースをエスケープする必要がないことはわかっていますが、この方法の方が読みやすいと思います。)

于 2012-06-08T21:19:04.033 に答える
1

これを使用してこれを行う方法は、 の位置に従って文字列の 2 つの部分を抽出するrindexために採用することです。substr{

これには{接尾部の が含まれることに注意してください。それを除外するに$i + 1は、2 番目のsubstr呼び出しで使用します。

my $str = "aa{bb{dccd";

my $i = rindex $str, '{';
my $pref = substr $str, 0, $i;
my $suff = substr $str, $i;

print $pref, "\n";
print $suff, "\n";

出力

aa{bb
{dccd

アップデート

substr1回の操作で分割を回避して実行したいというあなたの希望について読みました. unpackこのように、あなたのためにそれをします

my $str = "aa{bb{dccd";

my $i = rindex $str, '{';

my ($pref, $suff) = unpack "A$i A*", $str;

print $pref, "\n";
print $suff, "\n";

前のコードと同じ出力が得られます。

于 2012-06-08T19:58:39.820 に答える
0

そうですね、これを回答として投稿します。これが私が得た距離です。

これらのリソースに感謝します:

...「中かっこ」正規表現演算子について学びました。これは、「{n}直前の文字または文字範囲に正確に n 回一致します」。したがって、次のように一致できます/.{5}(.)/

perl -e '
$aa="aa{bb{dccd" ;
$aa =~ /.{5}(.)/  && print "--${1}--\n"; '

--{--

これにより、最初の5つの「任意の」文字が選択され、次の文字が選択されて印刷されます。または:

/               # start regex
 {              # match "{" character
  {5}           # repeat previous five times
     (.)        # select into match group (the $1) next character
        /       # end regex

最後に、 を使用しrindexてこのような分割を実行できます。

perl -e '
$aa="aa{bb{dccd" ;
$ri = rindex($aa, "{") ;
$aa =~ /.{$ri}(.)/  && print "--${1}--\n";
@res = split(/^.{$ri}(.)/, $aa);
print join("; ", @res) . "\n"; '

--{--
; {; dccd

..しかし、開始時にいくつかのキャプチャも必要であることを考えると、他のバリアントは次のとおりです。

@res = split(/^(.{$ri})(.)/, $aa);

--{--
; aa{bb; {; dccd


@res = split(/^(.{$ri})./, $aa);

--{--
; aa{bb; dccd

...どちらも私にとってはうまくいくでしょう-最初の項目として空白があることを除いて、1回のパスで( extra を呼び出さずにsplice)取り除きたいのですが、方法がわかりません:)

乾杯!

于 2012-06-08T19:50:22.640 に答える