Perl初心者スレ(マジレス回答)
遅くなりすみません。
テストファイルには改行を入れていなかったのですが、
chompが必要なのですね。
ファイルからレコードを取得するにはchompが必要と勉強になりました。
ありがとうございました。 >>450
いや、改行は入っていると思うぞ。でなければあのプログラムでは一致する。 ところでUTF-8にBOMってなんか意味あるの?
ビッグエンディアンで上のビットから詰め込んで並べている1パターンしかないよね? >>453
あるよ、BOMがあればUTF-8だと文字コードを
簡単に判定できる
つまり、文字化け防止に役立つ
みんなBOM付けるようにすれば良かったんだけどな >>450
ですが、改行が入っていました。
遅くなりすみません。
すみませんでした。確認をしっかりします。
もう一つ質問があるのですが、>>450の環境にて、パターンマッチングを、全角、半角、ひらがな、カタカナ、大文字、小文字を区別することなく行いたいのですが、方法をご教示いただけますでしょうか。 >>456
手順としてはまず比較に都合のいいように比較する側とされる側の文字列を正規化する。
例えば半角は全て全角にし、濁点や半濁点はそれを含んだ文字にし、英小文字は大文字にする。
それから比較を行う。
ただし使われている文字がASCIIの文字だけならば // のオプションで i が使えるので正規化不要。 教えて下さい。
my @str4=['a','b','c','d','e'];
my $ref4=\@str4;
print $str4[0][1],"\n"; # b
print @{ $str4[0] },"\n"; # abcde
ref4を使って同様に b と abcde を表示するには、どうしたらいいですか? うっかり自己解決しました。数時間悩んだのに。
print @{ ${ $ref4 }[0] };
print @{ ${ $ref4 }[0] }[1]; >>457
オプションで可能であればと思ったのですが、マッチング文字列と対象を同じ文字種にしないといけないんですね。
ActivePerlでUnicode::Japanese
でUTF8から変換して書いてみたのですが、cp932にencodeすると、化けてしまい、使用できませんでした。
ActivePerlで使用可能なモジュールあればコードではなくてかまいませんので、何かあれば紹介してもらえますでしょうか。 UNICODEにはcomposed、decomposedというややこしいものもあるんだよね。
https://pointoht.ti-da.net/e8205606.html
Unicode::Normalizeってのがあるけど、日本語を特別扱いしてくれたりはしなさそうな予感。 >>453-455
Linux では、BOM なしUTF-8 を使う、アプリ開発者が多く、
BOMありにするとバグるアプリがあるから、BOMなしを使っているけど、
そうすると、Windows では、sjis と区別がつかなくなり、
Explorer での文字列検索ができなくなる
だから、Windows10 で、WSL, Ubuntu を導入して、grep を使っている 結合文字列をUnicode正規化で合成する方法の危険性
https://qiita.com/monokano/items/d4c37d9bc9833eaeda6e
濁点・半濁点を別の1文字として扱う、結合文字列はMac だけだから、Mac を使わないなら関係ない
Unicode正規化は、日中韓で、別の漢字に変換されるものがあるから使えない
Ruby では、sjis・UTF-8 の変換は、ファイル読み書き時に指定できる。
CRLF・LF の改行コードの違いは、意識したことがない。
chomp とか、どちらの改行コードでも、正常に動く 【 nkf 】コマンド――文字コードと改行コードを変換する
http://www.atmarkit.co.jp/ait/articles/1609/29/news016.html
これで全角・半角の変換もできる
Perl にも、モジュールもあるのでは? >>464
有料ですがnkfのActivePerl用をnamazuというところから購入しましたが、
nkfで変換後、utf8でマッチングが不可能で調査中です。 ハッシュを要素に持つハッシュへのアクセスについて
ご教示いただけますでしょうか。
下記のコードで、読込は正常に完了しますが、出力が不可能です。
$$を使用したり、試しましたがギブアップです。
#hash.txtの中身(タブ区切り)
#1 10 テスト1
#2 5 テスト2
use Encode;
use utf8;
my %table;
my %rec;
open (FILE, "<:utf8", "hash.txt") or (die "$!");
while(my $line = <FILE>){
chomp($line);
@d = split(/\t/, $line);
%rec = ('id' => $d[0], 'count' => $d[1], 'name' => $d[2]);
$table{$d[0]} = \%rec;
print encode('cp932', $table{$d[0]}{'id'})."\t". encode('cp932', $table{$d[0]}{'count'})."\t".encode('cp932', $table{$d[0]}{'name'})."\n";
}
close(FILE);
print Encode::encode('cp932', "読込完了\n");
foreach my $row (@$wrote_num){
#出力不可能
print encode('cp932', $row{'id'})."\t". encode('cp932', $row{'count'})."\t".encode('cp932', $row{'name'})."\n";
}
print Encode::encode('cp932', "$出力完了\n"); wrote_numが何か分からんけど
my %rec; はwhile内にしたらどうですか
あと、$rowはハッシュのリファレンスだろうから$row->{'id'}では >>467
すみません、レス用に書き換えた元がwote_numでした
下記の様に変えましたが、アクセスできません。
意外と難しいですね。
use Encode;
use utf8;
my %table;
open (FILE, "<:utf8", "hash.txt") or (die "$!");
while(my $line = <FILE>){
chomp($line);
@d = split(/\t/, $line);
my %rec = ('id' => $d[0], 'count' => $d[1], 'name' => $d[2]);
$table{$d[0]} = \%rec;
print encode('cp932', $table{$d[0]}{'id'})."\t". encode('cp932', $table{$d[0]}{'count'})."\t".encode('cp932', $table{$d[0]}{'name'})."\n";
}
close(FILE);
print Encode::encode('cp932', "読込完了\n");
foreach my $row (@$table){
print encode('cp932', $row->{'id'})."\t". encode('cp932', $row->{'count'})."\t".encode('cp932', $row->{'name'})."\n";
}
print Encode::encode('cp932', "$出力完了\n");
実行結果:まだアクセスできません
>hash_test.pl
1 10 テスト1
2 5 テスト2
読込完了
出力完了 これでいけると思いましたが、玉砕でしたw
foreach my $row (@$table){
while (my ($id, $count, $name) = each(%row)){
print encode('cp932', "$id\t$count\t$name\n");
} これでいけました!
foreach my $row (keys %table){
print encode('cp932', "$table{$row}{'id'}\t$table{$row}{'count'}\t$table{$row}{'name'}\n");
}
>hash_test.pl
1 10 テスト1
2 5 テスト2
読込完了
1 10 テスト1
2 5 テスト2
出力完了
ただ、key を外して foreach my $row (%table)とすると下記の通り改行が入ります
1 10 テスト1
2 5 テスト2
出力完了 これで全てのハッシュ要素を出力できますが、
カラム順が不確定になってしまいますね。
ハッシュなので仕方ないことですかね。
foreach $row (sort keys %table) {
foreach $col (sort keys %{$table{$row}}) {
print encode('cp932', "$table{$row}{$col}\t");
}
print "\n";
}
>hash_test.pl
1 10 テスト1
2 5 テスト2
読込完了
5 2 テスト2
10 1 テスト1
出力完了 >>471
キーだけ別の配列に取っといてそれ使えば? >>472
できれば要素をカラム名でアクセスしたいのでハッシュの方がいいのですが、カラム順固定出力は配列しかないということですね。 >>471
foreach $col (sort keys %{$table{$row}}) {
を
foreach $col (qw/id count name/) {
とかでは? keyの名前も順番も分かってるんだし。 自分が昔質問したことにたいして今なら回答できる
<> は <STDIN> の単なる略ではなく
@ARGV が捕れない副作用があった
そこに詰まっていた
#!/usr/bin/env perl
use 5.010;
if (-p STDIN) {
print "May be pipe is used. I've got STDIN as below\n";
# my @lines = <STDIN>; # when <> used, perl think no @ARGV
map {state $i; ++$i;print "$i $_" } <STDIN>;
}
else {
print "This may be just single running.\n";
}
map {state $i; ++$i; print "$i argment found ==> $_\n"} @ARGV; タグを除去したいのですが、<>も文に入っているため
<.*?>ではなく<("[^"]*"|'[^']*'|[^'">])*>を使いたいのですが
perl -pe '<("[^"]*"|'[^']*'|[^'">])*>'
にする場合どれどれをエスケープすればよいでしょうか?
’だけだと動きませんでした。
perl -pe '<("[^"]*"|\'[^\']*\'|[^'">])*>' 除去?だったらs/パターン//gみたいにやらないと何も変わらないのでは?
てか、それエラーにならないの? 5chの書き込みのほう、つけ忘れてました
perl -pe 's/<("[^"]*"|'[^']*'|[^'">])*>//g'
です
perl -pe 's/<.*?>//g'は動くんですけど
perl -pe '<("[^"]*"|\'[^\']*\'|[^'">])*>'だと動かないんですよね またやっちゃった
perl -pe 's/<("[^"]*"|\'[^\']*\'|[^'">])*>//g' こうか?
perl -pe 's/<("[^"]*"|'"'"'[^'"'"']*'"'"'|[^'"'"'">])*>//g'
perlというよりシェルのシングルクォートの問題 そこまでするくらいなら HTML::Parser を使う方がいいと思うよ。 >481
できました!、ありがとうございます。
'を'""'で括るのですね
なんで\でエスケープにならないんでしょうね パーサーも一度使ってみたんですが
<p>hoge</p><p>hoge</p>
pタグが一行に2つあると誤作動したりするんですよね その誤作動がパーサーのせいかどうかは判らないが、少なくとも
HTML::Parser でそんなことは起こらないから安心してほしい。
たとえばテキスト部分だけを出力したいならこんな感じでできる。
my $parser = HTML::Parser->new(
text_h => [sub { print( $_[0]) },'text'],
);
$parser->parse_file( \*STDIN); >485
参考になります。
パーサーもいろいろ種類あるみたいですね。
自分の使ってたのはhtml-xml-utilsというやつでした。 @aに0を100ケ追加するには、pushをforで100回回す以外の方法ありますか >>488
ありがとうございました
俺が遅くなりまして申し訳ありません 二つ以上の空白文字列を
一つの空白に変えたいのですが
うまくいきません。
if($line=~/\s\s+/){
$line=~s/\s\s+/\s/g
print("$line\n")
} s/\s\s+/ /g;
でうまくいったよ。
そうか、\sって正規表現だから、置換文字列に使うと「perl にそんな定義ないで!」ってなるのか。
これは俺も気を付けよう。 置換といえばこのまえ、JSONで取得したUnicodeを表示したくて、
\u3042 → \N{U+3042}
に置換しようとしたけど、できなかった。
\N{U+ }←ここにはリテラルしか書けないのかな。 if文で真偽値を判定するのってどうやるの?
hoge() or die("Error\n");
ってなってた(hoge()の戻り値が魏ならエラー)のを標準出力したくて
my $a = hoge();
if( ! $a ){ print("Error\n"); exit $!; }
みたいにしたんだけど、if文の書き方ってこんなんで良いの? >>494
0を返しても、0といb、文字(アスキーコード0x30)として扱われたりするから、俺は
if(scalar($a)) {
とか
if($a eq 0) {
とかするよ。 >>494
良い。
! で条件反転させるんだったら unless 使っても良いと思うけどね。
unless ($a) { ... } みたいに。 良くないんだってば。
Perlをそういう流儀でやってるといつか痛い目にあうよ。 >>495
マジか。
my $a = hoge();
において、左辺が 0、右辺が 0x30 になるのは、言語としてぶっ壊れているんじゃね? そういう言語なの
0 but true
なんていう値もあるし 元の
hoge() or die("Error\n");
が問題なく動いてるなら
hoge() or print("Error\n"), die $!; hoge()が0を返しうるかどうかもわからんと思うのだが
>元の
>hoge() or die("Error\n");
>が問題なく動いてるなら
という前提の下で >>495 の配慮に意味があるの? >>496 で十分
hoge() or が動くという前提を無視するとして
もしもhoge()が0を含む数値か失敗を返すなら(空文字を含む文字列か失敗でもいい)
失敗にundefを返してdefinedで受けるのがフツー $_ ← これ、なんて読む?
perlが発祥ってわけでもないそうだが(bashとかにもあるんだってね)、ガチのドザなので
俺は内心ドルバーって呼んでる ドル・アンダーバーじゃないかな。
設定によってはチルダの代わりにトップバーってのがあったから、それと区別するのにアンダーって言ってた気がする。 おつあり
そういやそんなの(トップバー)あったねえ なるほど なつかしのcgiゲームを設置したくてperlを触ってるのですが、今の時代でもcgiゲームはサーバーへの負荷は大きいのでしょうか?(昔はよくゲームの設置が禁止されてましたが)
perlと関係なかったらすみません… StrawberryPerlで
$str='あ';
if ($str =~ /^[あいう]$/) {print("match\n");}
を実行してみるとマッチしてくれません
/^(あ|い|う)$/ ならマッチするのですが
古いPerl4のjperlなら /^[あいう]$/ でもマッチします
やはりこれはStrawberryPerlのバグ(または仕様)なのでしょうか print length $str; を入れてみたらわかる >>511
レスどうもです
Shift-JISの環境で正しく2とカウントされてます
前記はあくまで例ですので全角文字なら他の文字でもこうなるみたいで
ひらがなにマッチさせたいわけではないんです 少なくともperl5.8以降の文字クラスはuse utf8;前提になっててlengthが1じゃないとだめじゃね? 推奨されてないけど
use encoding 'sjis'
ならsjisでコード書けたと思う
jperlナツカシス Windows では Filter::Encoding いれて使ってた
スクリプトは utf-8 で書いて use utf8 してたけど
コマンドラインでは -MFilter::Encoding=cp932 とか