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年9月2日土曜日

Python2用ではなく、Python3のIDLEを導入する

ubuntu16.04.*


新規にターミナル(端末)を開きます。CTRL+ALT+T
#
 sudo apt install idle3
#起動 3が必要。
idle3

#以上です。たぶんこれでいいと思います。

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のインストール候補になった気がします。

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


2017年5月22日月曜日

利用中シェルに応じてコマンドを使い分ける。bash or zsh

zshとbashを同時並べつつカスタマイズしている最中に便利なコマンドであり、その雛形です。
  • zsh/bashでプロンプトの形や色などで変えていても間違えることがある。
  • キーバインドの統一カスタマイズ作業をしている最中はとりわけ混乱する。
  • 実はかなり間違えている。年に10回以上は:笑)
ので

以下をぺったんして、(当方はシェル関数はbash/zsh 共通のrcファイルにしています。共通で動かない関数は原則使いません。メンテがめんどうだからです。意識は高くないです。~/.bash_functions.rc にzsh/bash共通利用関数を書いています)
以下の実使用中の雛形では、bashrc または zshrc と打てば、rcファイルへの変更が反映されます。shrc というコマンド名もないはずなので、そういうので統一してもいいでしょう。

余談ですが、このパターンを利用して ~.keybindings というキーバインディング設定rcを.zshrc/.bashrcから読み込ませています。
#bash単独ならもちろん不要。
#@ シェル関数定義
#

    function bashrc () {
        #bashrc/zshrc で rc をシェルに応じて再読込。カレントシェル判別。
        CURRENT_SHELL=`set | grep -aoP '^(B|Z)A?SH_VERSION'`

        case $CURRENT_SHELL in
            BASH_VERSION )
              source ~/.bashrc && echo 更新完了 source ~/.bashrc ;;
            ZSH_VERSION  )
              source ~/.zshrc  && echo 更新完了 source ~/.zshrc  ;;
            *)
                echo not zsh , not bash  ;;
        esac
    }
    alias zshrc=bashrc
#zshrc としても、bashrcとしても、同じ。

# BASH_VERSION='4.3.46(1)-release'
# ZSH_VERSION=5.1.1
# csh / tcsh / fish (^fish_)などは使いませんのでこれで充足しています。

#~/.bashrc .zshrc

 if [ -f ~/.keybindings ];         then  .  ~/.keybindings    ; fi

#~/.keybindings

CURRENT_SHELL=`set | grep -aoP '^(B|Z)A?SH_VERSION'`
case $CURRENT_SHELL in

ZSH_VERSION  ) 
#ZSHはここから定義。
    bindkey "\e[3;2~" kill-word  #bash/zsh 共通
    bindkey '^x^e' edit-command-line #FC と等価 bash 標準アサインと統一した。
      ;;

BASH_VERSION )  #BASHはここから定義。

#■ ALT-シリーズ
    bind '"\ea":beginning-of-line' #alt-a も行頭に戻る。この妥協が一番よさそう

;;
esac
#.inputrc に設定するよりこっちのほうが自分は楽。

青色の行でシェル名が変数に格納できますので、bashならほげ、zshなら、ふげというシンプルなcase分岐ができています。(カレントシェルに応じて)同じようなことをしたいけれどコマンド名が微妙に違うってケースは、シェル内蔵コマンド bind(bash)/bindkey(zsh)などでもありますよね。

zsh/bashに特化していますので、
grep で、a=アスキー限定、o=一致部分切り出し、P= Perl互換正規表現
としています。これで、ZSH_VERSION という文字列がCURRENT_SHEL格納できるわけです。
~/binなどにはこの分岐を使った他のツールもおいています。

余談。grep の -Pオプションは、なんだかんだいっても便利です。Perl互換の正規表現だけ覚えていればいいのでGNUツールのみしか使わないって人にはうってつけかも。職業的なプログラマー、SEなどであれば様々なUnix環境に対応したいと思うのでしょうが、自分は関係ないので。そういえば、このオプションでなんとかなっているので、pcregrep/pcre2grep は使いませんね。以前はエクスペリメンタルだった気がしますが、今はカジュアルに使っていいのではないかと。


zshは素晴らしすぎ便利すぎです。だから人間があほになりそう!!とbashを使うんですが、zshもいいよな、と。10年位こんなことを繰り返しています。あはは。もっとインテリジェント、エレガントな解法があれば乗り換えますので、ご教授ください。

#~/.profile mint18.1の .profile(ログインシェルで読み込まれる?!)では次のように書かれていました。さっき気がつきました。


# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi