• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:文字列の切り出しとその文字列からの文末削除がしたい)

文字列の切り出しと文末削除の方法を教えてください

このQ&Aのポイント
  • 質問者は、Perlを使用して文字列の切り出しと文末削除を行いたいと考えています。
  • 具体的には、与えられたデータから特定の文字列を抜き出し、その文字列の文末を削除したいとのことです。
  • しかし、現在のPerlのコードでは望んだ結果が得られていないそうです。アドバイスを求めています。

質問者が選んだベストアンサー

  • ベストアンサー
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.11

>012345 6.6666ppm 2.6asc 3.9asc GOOD 0 0 >========= ==== >print OUT "$1,$2" if /^01234\d+\s+(-?[\d.]+)+\s+\d+\s+\d+s+(\d)/; \d は数字を意味しますので、(\d+) では GOOD を捕捉することはできません。GOOD, NO, MIN 等の大文字だけの単語をを切り出すには、([A-Z]+) を使うことができます。\s (空白類) と \S (空白以外) で行の構造にしたがって正規表現を組み立てると、捕捉することができます。 print OUT "$1,$2" if /^01234\d+\s+(-?[\d.]+)\S+\s+\S+\s+\S+\s+([A-Z]+)/; また、途中を読み飛ばす次のような方法もあります。 print OUT "$1,$2" if /^01234\d+\s+(-?[\d.]+).*\b([A-Z]+)/;

noname#72292
質問者

お礼

この度は色々とありがとうございました。 もう少しアドバイスいただきたいのですが当初の疑問は解消できました。ありがとうございました。

その他の回答 (10)

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.10

No9 の回答に書き間違いがありました。2行目の (-?[\w.]+) を (-?[\d.]+) に訂正します。

noname#72292
質問者

お礼

ありがとうございます。 もうひとつアドバイスをいただきたく、よろしくお願いします。 ・以下のように6.6666と合わせてGOODを出力したい時はどのように すればよいですか?うまくいきません。 012345 6.6666ppm 2.6asc 3.9asc GOOD 0 0 ========= ==== print OUT "$1,$2" if /^01234\d+\s+(-?[\d.]+)+\s+\d+\s+\d+s+(\d)/;

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.9

>1.抜き出す数字はマイナスのときはどうしたらよろしいでしょうか? 丸カッコの先頭に -? (- が0個または1個) を付けて、(-?[\w.]+)のようにすると抜き出すことができます。 >2.抜き出す数字の小数点以下が.0000のときはエクセルに出力するには? エクセルを使ったことがないのでお答えできません。 >3.012345と012346のデータ間で改行をいれるにはどうしたらよろしいでしょうか? # に囲まれた数字の行を利用することができると思います。次のコードは、先頭に数字そのものを 出力しています。 while (<GO>) { print OUT "\n$1," if /^#+(\d+)#+/; print OUT "$1," if /^01234\d+\s+(-?[\d.]+)/; }

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.8

次のような簡単なコードで十分ではないかと思います。ただ、BOOK に続く ###### は意味のあるデータとは思えませんが? while (<GO>) { print OUT "\n$1," if /BOOK(.+)/; print OUT "$1," if /^01234\d+\s+([\d.]+)/; }

noname#72292
質問者

お礼

回答ありがとうございます。 追加でお聞きしたいことがあります。どうかお答えいただきたく、 よろしくお願いします。 1.抜き出す数字はマイナスのときはどうしたらよろしいでしょうか? 2.抜き出す数字の小数点以下が.0000のときはエクセルに出力するには? 3.012345と012346のデータ間で改行をいれるにはどうしたらよろしいでしょうか?

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.7

レコード(行)の先頭にある空白の扱いが微妙に違いますが、 フィールドの区切りに関して言えば、/ / は単にスペース一個という 解釈はされませんので、修正する必要はありません。 As a special case, specifying a PATTERN of space (' ') will split on white space just as "split" with no arguments does. Thus, "split(' ')" can be used to emulate awk's default behavior, whereas "split(/ /)" will give you as many null initial fields as there are leading spaces. A "split" on "/\s+/" is like a "split(' ')" except that any leading whitespace produces a null first field. A "split" with no arguments really does a "split(' ', $_)" internally. >後日譚。今思えば、この正規表現は全然へなちょこでした。 >[+-]?\d*?.?\d+ 小数点を表すピリオドはエスケープする必要があるのではありませんか? まあそういうことで。

回答No.6

4行目を my ($num, $ppm) = split / +/; とすれば、スペース1個以上で分割できます。なお、より一般的に空白文字で分割するには: my ($num, $ppm) = split /\s+/; こんな感じですね。 7行目 push @ppm, $ppm =~ /(\d?.?\d+)/; にご注目ください。 後方参照のためのグループ化を使用した正規表現によるパターンマッチをリストコンテキストで評価すると、マッチした部分をリストで返します。 ――つまり、カッコ内の正規表現にマッチしたやつが、@ppm に追加されるわけです。 ところで、「カッコ内の正規表現」って何でしょうか ? \d?.?\d+ ↑実はこれは、数字部分にマッチする正規表現です。 数字部分のみを抜き出して、@ppm に追加することができるわけです。 数字以降にいかなる文字列があろうとも、数字だけを抽出することができます。 後日譚。今思えば、この正規表現は全然へなちょこでした。 [+-]?\d*?.?\d+ せめてこれくらいはしないとダメですね。

回答No.5

間違えました。正しくはこちらです。 ---------- my @ppm; while (<GO>) { my ($num, $ppm) = split / /; next unless defined $num and defined $ppm; next unless (substr $num, 0, 5) eq '01234'; push @ppm, $ppm =~ /(\d?.?\d+)/; } print OUT join ',', @ppm; ---------- 7c7 < push @ppm, $ppm; --- > push @ppm, $ppm =~ /(\d?.?\d+)/;

noname#72292
質問者

補足

回答ありがとうございます。 いつくか教えていただきたいことがあります。 (1)文末がpppmやpmの文字列も「my @ppm;」で抜けるのはなぜですか? (2)下記のようにスペースが長いときもあるのですがそれも考慮して、 抜き出す方法はございますか? 012345      6.6666ppm 2.6asc 3.9asc GOOD 0 0 よろしくお願いいたします。

回答No.4

my @ppm; while (<GO>) { my ($num, $ppm) = split / /; next unless defined $num and defined $ppm; next unless (substr $num, 0, 5) eq '01234'; push @ppm, $ppm; } use 5.010000; say OUT join ',', @ppm;

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

なんとなくこういうこと? use strict; use warnings; use feature ':5.10'; open my $output, '>', 'sample.out'; while(my $line = <DATA>){ chomp $line; if($line =~ /BOOK(.+)/){ print $output "\n$1,"; } #01234を見つけたら、一番最初の文字列を抜き出す if($line =~ /^01234/){ my ($num, $item1, $rest) = split / /, $line; print $output "$item1,"; } } close $output; __END__ #####BOOK###### ###################33########################## 012345 6.6666ppm 2.6asc 3.9asc GOOD 0 0 012345 1.6666pm 2.6asc 3.9asc NO 0 0 012345 6.6656pppm 2.6asc 3.9asc MIN 0 0 ###################36########################## 012346 6.6666ppm 2.6asc 3.9asc GOOD 0 0 012346 1.6666ppm 2.6asc 3.9asc NO 0 0 012346 6.6656ppm 2.6asc 3.9asc MIN 0 0 結果 ######,6.6666ppm,1.6666pm,6.6656pppm,6.6666ppm,1.6666ppm,6.6656ppm, 最初に空行はいるとか、末尾にも','が付くってのはたぶんNGなんでしょうねえ。 んで、元データの#の行をじーっとみてみて 33,6.6666ppm,1.6666pm,6.6656pppm 34,6.6666ppm,1.6666ppm,6.6656ppm とか 33,6.6666ppm,2.6asc,3.9asc 33,1.6666pm,2.6asc,3.9asc 33,6.6656pppm,2.6asc,3.9asc 34,6.6666ppm,2.6asc,3.9asc 34,1.6666ppm,2.6asc,3.9asc 34,6.6656ppm,2.6asc,3.9asc みたいな結果がほしいのかなあと思わないでもないんですがどうなんでしょうか?

noname#72292
質問者

補足

説明がうまくなく、すいません。 出力イメージは以下のような感じです。 ●出力イメージ 6.6666,1.6666,6.6656,6.6666,1.6666,6.6656,

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

スクリプトを見ても、正規表現がめちゃくちゃなので欲しい結果がどういうものかわかりません。 >012345 6.6656pppm 2.6asc 3.9asc MIN 0 0 >012346 6.6656ppm 2.6asc 3.9asc MIN 0 0 >上記のようなデータから一番左の文字列があったら、 >一番最初の文字列を切り出し,文末を削除したいのですが、 >作成したperlでは6.6666ppm 2.6asc 3.9asc まで切り出して且文末が削除できません。 一番左の文字列を切り出し文末を削除というのは この例だと 6.6656ppm だけとれればいいんですか?

noname#72292
質問者

補足

>一番左の文字列を切り出し文末を削除というのは >この例だと 6.6656ppm だけとれればいいんですか? はい。それでppmを取りたいです。 簡単ですが、よろしくお願いします。

noname#96023
noname#96023
回答No.1

いまいちとりたい出力がわからないのですが、 私だったらこうかな(試してないので文法の正確さはわかりません) @list = split( / / , $_ ); printf "%s %s %s\n", $list[1], $list[2], $list[3];

関連するQ&A