ラベル perl の投稿を表示しています。 すべての投稿を表示
ラベル perl の投稿を表示しています。 すべての投稿を表示

2018年7月22日日曜日

Python のスクリプトをPerlで修正する。Python2をPython3対応にするプチ事例

PythonソースコードをPerlでさくっと修正してみる

新規にターミナル(端末)。CTRL+ALT+T

2to3 という、 「Python 2.x のソースコードを読み込み、一連の 変換プログラム を適用して Python 3.x のコードに変換するプログラム」がありますので、本来の目的用ではなく、Perlのワンライナー活用例として示しています。


元のファイル、python000.py (Python2用 3行ファイル)

# coding: utf-8
print "パイソン世界2から3への代表的な例::2to3が用意されている\n覚えておくといいかも。"

exit()

実行

$ python2 python000.py
パイソン世界2から3への代表的な例::2to3が用意されている
覚えておくといいかも。

Python3で実行しようとすると怒られる。
$ python3 python000.py
                                          ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print

なるほど、printの扱いが変わったのですね。これを修正します。修正の仕方も教えてくれる親切Pythonです。

$ perl -wlpe 's/\b(print)\b.*\"(.*)\"/$1 ("$2")/;s/\# coding: utf-8//' ./python000.py

1) プリント行を()で囲む仕様変更。
2) # coding: utf-8 は不要なので削除する。

まとめて実行、1ライナーで修正して保存、そのまま実行
$ perl -wlpe 's/\b(print)\b.*\"(.*)\"/$1 ("$2")/;s/\# coding: utf-8//' ./python000.py | tee python003.py && echo "終 実行"; python3 python003.py
print ("パイソン世界2から3への代表的な例::2to3が用意されている\n覚えておくといいかも。")
exit()
終 実行
パイソン世界2から3への代表的な例::2to3が用意されている
覚えておくといいかも。

$ python3 python003.py

としても当然同じなので、これでOK。

まとめ::結局bash上の使い方事例なのです

$ perl -wlpe 's/\b(print)\b.*\"(.*)\"/$1 ("$2")/;s/\# coding: utf-8//' ./python000.py |\
 tee python003.py \ 
 && echo "終 実行";\
 python3 python003.py
パイプ、接続をばらして説明すると
1行目、PerlでPrintする内容を正規表現でキャプチャしておいて、Python3仕様に変換。不要なUTF-8行を削除
2行目、Tee で結果(Python3で動く内容)を出力しつつ新たなファイル(python003.py)に保存する
3行目、作業が終わった目印を出力して(冗長:なくてもよい)
4行目で、Python3で新規に生成されたスクリプトファイル(python003.py)を引数として実行して、動作することを確認する。
こういう流れですね。teeはなくてもこまらないけれど、ないとめんどくさいコマンドかなと思います。地味に便利な子です。



2018年7月17日火曜日

Perlで文字列置換 sed

テキストファイルの文字列を置換する

新規にターミナル(端末)。CTRL+ALT+T

最も単純な置換処理
perl -lpe 's/対象文字/置換後文字/g' テキストfile


解説::
最期の/gでグローバルに全部置換。gがなければ最初に見つかったひとつのみ置換。

オプション::
l 自動chomp。改行を除去するなど行処理をいいかんじにしてくれる。
p ループ構造で実行してくれる。この場合Whileループがたった1文字で実現。
e 以下を計算式、命令として実行。この例は置換ですがそれ以外も使えます。
E にすると、sayなどが使えますので、Eで覚えたほうがいまどきいいかも。 
Perlがワンライナーでいいかんじに処理してくれる好例です。gは常に付ける癖にしておいて、不要な時のみ外すようにしたほうが捗ると思います。

複数置換は、置換命令を連続して重ねていけばだいじょうぶ
perl -lpe 's/対象文字/置換後文字/g;s/対象文字/置換後文字/g;s/対象文字/置換後文字/g' テキストfile

Perlの置換の書式は、sedと同じです。sed/viに倣って設計されているからです。

大量の置換処理が必要な場合は、sed同様ワンライナーよりもスクリプトファイルをテキストエディターで作成して実行するほうが得策です。

Perlの使い始めのうちは、こうしたものはパターンとしておぼえてしまうと楽かと思います。

最大のメリットはPerlを使うことでPerlの正規表現だけ覚えればOKということです。sedであれば微妙に動作が違うわけだし、OS問わず同じですから。めんどうを回避できます。

sedを超えるPerlのsed風味な機能は別稿にします。

おまけ:: Perl6 で正規表現テスト
ls | perl6 -pe 's:g/^.*?\.(.*)$/$0/ ;'

ファイルがいくつかあるディレクトリで実行してみるとよいです。ファイル名は置換されません。画面の結果だけですのでご安心を。

カレントにあるファイルのファイル頭からドットまでを削除して表示。ドットがなければそのフィアルをそのまま表示。

Perl5との違いは、キャプチャかっこの番号が0からになっている点。この場合のgは不要ですが、前に来ます。:が必要です。など。複雑になっていくとPerl5のようにはいきません。デリミタの自由度はとても高いです。


2018年7月1日日曜日

perlrange::指定範囲を抜き出すコマンド | シェル変数を受け取る::bash関数

Perlで範囲を抜き出す。特定範囲のみ加工する。

日本語ドキュメントの取り扱いが主ですが、用語と用語、行番号と用語などで範囲を想定し、Perlに備わっている機能を使ってテキストファイルから行を抜き出すのに、こんな風に使っています。

sオプションでシェル変数を受け取ります。関数やスクリプトにする場合に覚えておくと便利です。この関数は、Zsh/Bash共通でいけると思います。

新規にターミナル(端末)。CTRL+ALT+T
#
使い方
perlrange 範囲始まりに含まれる行の単語  同じく終わりの行の単語

.bashrc などにぺったんする。

function perlrange () {
        # s オプションでシェル変数受け取れる。qw注意。
        # if [ $# -ge 1 ]; then
        if [ $# -eq 2 ]; then
                perl -nse "print if /$1/ .. /$2/"
           

        else
            echo 説明....

            echo 範囲A-Bを入力。Bが存在しなければ最後まで。
        fi
     }



余談

perl -ne 'print if 10 .. 12'
10行目から12行めから抜き出す。正規表現にしなければ$_行番号になります。

perl -ne 'print if 10 .. /マンゴージュース/'
10行目からマンゴージュースまで抜き出す。正規表現と行番号も組み合わせできます。
 
cd ~ 
ls | sort -r | perlrange Pic Desktop
なんて2行タイプするとイメージがつかめていいかもしれません。
  

2017年9月11日月曜日

gnu grep のススメ、Perl互換オプションのススメ::あえて2017年に叫ぶ

gnu grep が使える環境なら、素直にgnu grep を使おう


新規にターミナル(端末)を開きます。CTRL+ALT+T

#PCRE(Perl正規表現互換オプション)

grep -P '検索文字列'

エクスペリメンタルな位置づけも終わっていますので安心です。サブセットかと思っていたら、(否定|肯定)(先読み|後読み)も使えますよ。グッドです。ただひとつ、Perl5な場合では文字数の限定などがあるので、ちょっと不便ですね。

gnu grepが使えない環境では、pcre2grep/pcregrep がありますが、あんまり使いません。

おおむね、grepの -Pオプション(大文字です。小文字にしても怒られるだけなのですぐに気が付きます)でだいじょうぶ。

私の場合、ほとんど日本語処理目的なのですが自分の用途では困ったことがないです。

#Perlのワンライナーの一例

perl -lne "print if /検索文字列/" ファイル
perl -lnE "say   if /検索文字列/" ファイル
perl -lnE " /検索文字列/ and say" ファイル

grepの色分け機能などを実装するのはたいへんですから、素直にGNU Grepがよいです。
改行がかならず必要なら、say で書いていったほうがタイプ数が少ないです。
当職はトラブった時しか考えないのですが、クオートはシングルが基本なので、
見本は不適切ってことかもしれません。直せよ。^^;


MACはGNU grepではないらしいので、pcregrep/pcre2grepが良いのではないでしょうか。
私はカジュアルなLinux使いなので、深いことは気にしません。笑) pcre2grepで統一してもいいかもしれません。

方針としては、できるだけ簡素に、学習することなく、空気のように端末を扱うです(努力だけはしたくない)。だから、正規表現はPerl互換の正規表現だけが原則です。プロの方は瞬時に脳みそ切替しながら使うのかもしれませんけれど。

#perl 5 互換の正規表現を利用する grep ユーティリティ pcregrepをいれたい場合。ubuntu/mint

導入する
sudo apt install pcregrep

削除する
sudo apt purge pcregrep
...

きょう現在、当方にはいっているgrep

pcre2grep --version
pcre2grep version 10.21 2016-01-12

pcregrep --version
pcregrep version 8.38 2015-11-23

zpcregrep --version
zgrep (gzip) 1.6
Copyright (C) 2010-2013 Free Software Foundation, Inc.


grep --version
grep (GNU grep) 2.25

Copyright (C) 2016 Free Software Foundation, Inc.



#複数行にわたるgrepの例::Perlのワンライナーのほうが楽だよねといわれそうだけど。

perlのワンライナーのほうが楽だけど、grepでもちょろいので知っていて損はないという例。

こういうファイル。9行。
cat -n delete.txt
     1 会いたい
     2 藍Ⅰ姶
     3 藍と愛と藍
     4 藍藍
     5 藍藍青
     6 群青
     7 藍藍
     8 藍と終と
     9 藍マイ。


マッチした範囲に色。色がなければ無能。
$ grep -Pz  '愛.*(\n|.)*終' delete.txt
会いたい
藍Ⅰ姶
藍と愛と藍
藍藍
藍藍青
群青
藍藍
藍と終と
藍マイ。

※zオプションで行単位処理でなくなり、 
(\n|.)で改行またはなんかの1文字にマッチさせる。
perlでいえば、セパレータ変えての/smオプションってことですね。


範囲切り出し::オススメなo オプション、有能
$ grep -Pzo  '愛.*(\n|.)*終' delete.txt
愛と藍
藍藍
藍藍青
群青
藍藍
藍と終

含まれている行を表示
$ pcre2grep -M  '愛.*(\n|.)*終' delete.txt 
藍と愛と藍
藍藍
藍藍青
群青
藍藍
藍と終と

$ pcregrep -M  '愛.*(\n|.)*終' delete.txt 
藍と愛と藍
藍藍
藍藍青
群青
藍藍
藍と終と

マニュアルで詳細は確認してください。

pcre2grepの動作をperlでやるとすれば、範囲を抜き出すかんじ。

perl -nle  'print if /愛/ ... /終/' delete.txt


PCRE2grepとPCREgrepの違い


前者が新しい10系列以降になります。後者はメンテされていますが8系列です。ubuntu標準では8系列です。自分がどうやってpcre2grepをいれているのかは思い出せません。コンパイルしたのでしょうね。

PCREプロジェクトはケンブリッジ大学発祥のようです。
Cf. http://www.pcre.org PCRE - Perl Compatible Regular Expressions

2017年6月5日月曜日

Perl 「Wide character in print」 エラーに即時対応する。

Perlで華麗に日本語を扱う::モジュール篇

理由/原因には興味はないので必要ならググってもらうとして、

Ubuntuなどで ja_jp.UTF8 など(SHIFT_JISじゃあるまいに)を使っているのに発生して、Cpanモジュールなどが原因の場合、自分のスクリプトを書き換えずに、モジュールの方を書き換えています。

エラーでは行数が表示されますが、それは無視。当該hoge.pmに
#以下を追記
use utf8::all;

#libutf8-all-perl のインストールが必要です。
#sudo apt install libutf8-all-perl

arch系はcpan コマンドで導入しました。



自分の場合はこれでうまく対処できなかったことはありません。とても重宝しています。
試して損はないので考慮してみださい。とにかくコードが短く書けます!!
※問題があるモジュールがひとつありましたが、CPANモジュールまるごと差し替えました。何だったか覚えてません。

別言すれば、エンコードだのデコードだのはばからしいので考えたくもないのでした。
とても便利なのでもっと知ってほしいです。Printするだけならエラーを無視という手も通じる場合がありますが、日本語を含む名前のファイルを自動生成するスクリプトなどの場合はとんでもないひどい文字化けだったりしますから、この呪文一行で解決するなら安いものです。

以前はご多聞にもれず、私もエンコードだの、デコードだの、UTF8フラグをごにょごにゅするだの、ばかげたコードを書いていました。こんな非生産的な行為を「みんな」やっているんだろうか? とふと疑問になったのです。暇じゃないだ。

CPANでUTF-8という文字列で検索できるモジュールを全部(ほんとうに全部)試してたどり着きました。このモジュール紹介している日本語記事は執筆時点で私だけみたいですが、ほんと便利です。

それはそうと、Python3でも小物を作るのですが、Unicode文字が自在に使えて便利ですよね(その意味で最高!!)。

Perlでもこのモジュールlibutf8-all-perlを組み込むと変数に日本語ユニコード文字が使えます。使っています。このように、長文の文章ヒエラルキーに自動番号付けや整形を自動で行うPerlスクリプトを書いているのですが、わかりやすくていいです。ちなみに、Perl内で 自己紹介; とすると日本語が含まれているスクリプト名が表示される関数モジュールなんかを書いてます。日本語大好きです。

my 章
my 節
my 項

みたいにです。 3年前ぐらいにubuntuのインストール候補になった気がします。

※絵文字領域はだめでした。$🔥 は弾かれます。笑) $🐸 もです。