ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

MacやUbuntuでgrepでひらがな・カタカナ・漢字を検索する

過去の記憶では下記のように実行するとうまくいった覚えがあるようなないような。。。

$ cat hogehoge.csv | grep -E '[ぁ-んァ-ン0-9]' | head
grep: Invalid collation character

しかし、Ubuntuで実行するとよくわからんエラーが。。。

で、色々探したり教えてもらった結果、-Pオプションを使ってあげるとうまくいくことがわかりました。その辺をメモ。

その前に、MacOSの場合はggrepをインストールしてください。自分はMacOSのデフォルトでインストールされているgrepを扱うことはできないです。

$ brew install ggrep
$ alias grep='ggrep'

ひらがな、カタカナ、漢字を検索する

-Pを使うことでPerlで使われているものと同じ正規表現(Perl正規表現)をつかえるようにするとのこと。

greymd.hatenablog.com

$ cat hogehoge.csv | grep -P '\p{Hiragana}' | head # ひらがな
$ cat hogehoge.csv | grep -P '\p{Katakana}' | head # カタカナ
$ cat hogehoge.csv | grep -P '\p{Han}' | head # 漢字

orebibou.com

これでうまくいきました!!!!ここ最近違うOSごとに使える正規表現で苦しめられていたから泣きそうになってた(´・ω・`)

とりあえずうまくいったのでよかった

BigQueryで半角文字を全角にする

JavaScriptが使える(°Д°; この記事を参考にしました。

qiita.com

CREATE TEMPORARY FUNCTION normalize2(str STRING)
RETURNS STRING
LANGUAGE js AS """
if (str === null)
  return;

var kanaMap = {
  'ガ': 'ガ', 'ギ': 'ギ', 'グ': 'グ', 'ゲ': 'ゲ', 'ゴ': 'ゴ',
  'ザ': 'ザ', 'ジ': 'ジ', 'ズ': 'ズ', 'ゼ': 'ゼ', 'ゾ': 'ゾ',
  'ダ': 'ダ', 'ヂ': 'ヂ', 'ヅ': 'ヅ', 'デ': 'デ', 'ド': 'ド',
  'バ': 'バ', 'ビ': 'ビ', 'ブ': 'ブ', 'ベ': 'ベ', 'ボ': 'ボ',
  'パ': 'パ', 'ピ': 'ピ', 'プ': 'プ', 'ペ': 'ペ', 'ポ': 'ポ',
  'ヴ': 'ヴ', 'ヷ': 'ヷ', 'ヺ': 'ヺ',
  'ア': 'ア', 'イ': 'イ', 'ウ': 'ウ', 'エ': 'エ', 'オ': 'オ',
  'カ': 'カ', 'キ': 'キ', 'ク': 'ク', 'ケ': 'ケ', 'コ': 'コ',
  'サ': 'サ', 'シ': 'シ', 'ス': 'ス', 'セ': 'セ', 'ソ': 'ソ',
  'タ': 'タ', 'チ': 'チ', 'ツ': 'ツ', 'テ': 'テ', 'ト': 'ト',
  'ナ': 'ナ', 'ニ': 'ニ', 'ヌ': 'ヌ', 'ネ': 'ネ', 'ノ': 'ノ',
  'ハ': 'ハ', 'ヒ': 'ヒ', 'フ': 'フ', 'ヘ': 'ヘ', 'ホ': 'ホ',
  'マ': 'マ', 'ミ': 'ミ', 'ム': 'ム', 'メ': 'メ', 'モ': 'モ',
  'ヤ': 'ヤ', 'ユ': 'ユ', 'ヨ': 'ヨ',
  'ラ': 'ラ', 'リ': 'リ', 'ル': 'ル', 'レ': 'レ', 'ロ': 'ロ',
  'ワ': 'ワ', 'ヲ': 'ヲ', 'ン': 'ン',
  'ァ': 'ァ', 'ィ': 'ィ', 'ゥ': 'ゥ', 'ェ': 'ェ', 'ォ': 'ォ',
  'ッ': 'ッ', 'ャ': 'ャ', 'ュ': 'ュ', 'ョ': 'ョ',
  '。': '。', '、': '、', 'ー': 'ー', '「': '「', '」': '」', '・': '・'
};

var reg = new RegExp('[' + Object.keys(kanaMap).join('') + ']', 'g');

return str.normalize('NFKC')
  .replace(/[A-Za-z0-9]/g, function(s) {
    return String.fromCharCode(s.charCodeAt(0) + 65248);
  })
  .replace(reg, function (s) {
    return kanaMap[s];
  })
  .replace(/[\\s\\u3000]+/g, ' ')
  .trim();
""";
SELECT normalize2('1234ABCDabcd');

ハマったこと

関数名をnormalizeにするとエラー

仕方なくnormalize2にしました。多分同じ関数名がある?

Pythonのmodule「psycopg2」を使ってPostgreSQLへ接続する

PostgreSQLがインストールできたので今度はPythonから実行してみる

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1611

$ python -V
Python 3.4.5 :: Anaconda custom (x86_64)

$ psql --version
psql (PostgreSQL) 10.1

psycopg2のインストール

ちょっとだけぐぐってみたけど、PostgreSQLのドライバはこいつが人気らしいのでインストールする

www.ashisuto.co.jp

$ pip install psycopg2

叩いてみる

Pythonインタプリタで遊ぶ

$ python
Python 3.4.5 |Anaconda custom (x86_64)| (default, Jul  2 2016, 17:47:57)
[GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

あ、その前にこんなテーブルが作成されています。

create table sites (
  id bigserial primary key,
  site_name varchar(200) unique,
  created timestamp,
  update timestamp
);
>>> import psycopg2

# DB接続する
>>> conn = psycopg2.connect('dbname=db_name host=localhost user=userpassword=password')

# こいつがよくわからん
>>> cursor = conn.cursor()

# select文を実行
>>> sql = 'select * from example;'
>>> cursor.execute(sql)

# 実行した結果を取得
>>> results = cursor.fetchall()
>>> results
[(1, 'xxxxx', datetime.datetime(2018, 1, 27, 15, 49, 17, 977406), datetime.datetime(2018, 1, 27, 15, 49, 17, 977413)), (3, 'yyyy', datetime.datetime(2018, 1, 27, 15, 49, 55, 199015), datetime.datetime(2018, 1, 27, 15, 49, 55, 199017))]

# placeholder
>>> sql = 'select * from sites where site_name = %s'
>>> cursor.execute(sql, ('xxxxx', ))  # tupleは1つのときは最後にカンマ入れないとNG
>>> results = cursor.fetchall()
>>> results
[(1, 'xxxxx', datetime.datetime(2018, 1, 27, 15, 49, 17, 977406)]

# 数値も%sで良いっぽい
>>> sql = 'select * from sites where id = %s'
>>> cursor.execute(sql, (1,))
>>> results = cursor.fetchall()
>>> results
[(1, 'xxxxx', datetime.datetime(2018, 1, 27, 15, 49, 17, 977406)]

insertとかのデータ処理

トランザクション?が動いているっぽくて、cursorに命令したら実行はconnで実行しなければいけない。

# insert
>>> sql = 'insert into sites (site_name, created, update) values (%s, clock_timestamp(), clock_timestamp());'
>>> cursor.execute(sql, ('zzz',))
>>> conn.commit()

# update
# SQLでダブルクォーテーション使うとダメだった
>>> sql = "update sites set site_name = %s where site_name = 'zzz';"
>>> cursor.execute(sql, ('aaa',))
>>> conn.commit()

# update カラムも更新する
>>> sql = "update sites set site_name = %s, update = clock_timestamp() where site_name = 'aaa';"
>>> cursor.execute(sql, ('zzz',))
>>> conn.commit()

# delete
>>> sql = 'delete from sites where site_name = %s'
>>> cursor.execute(sql, ('zzz',))
>>> conn.commit()

ほい。こんな感じで動きました(ちょっと大変だった

serialを使っているテーブル名を変更するときの注意

PostgreSQLこんなテーブルを作った

create table site_categories (
  id bigserial primary key,
  site_name varchar(200) unique,
  created timestamp,
  update timestamp
);

で、途中で名前を間違えていることに気づいた。サイトのカテゴリではなくて、サイト名を入れたかっただけだったから。

> alter table sites_categories rename to sites;

おk

んで、これでいけると思ったが。。。

このテーブルへの処理しようとすると応答が返ってこなくなった。

おかげさまでプロセスを切る方法を学んだ

$ psql -q -c'SELECT l.pid, db.datname, c.relname, l.locktype, l.mode FROM pg_locks l LEFT JOIN pg_class c ON l.relation=c.relfilenode LEFT JOIN pg_database db ON l.database = db.oid ORDER BY l.pid;' -d db_name

  pid  | datname | relname  |  locktype  |      mode
-------+---------+----------+------------+-----------------
 28376 | db_name  | pg_locks | relation   | AccessShareLock
 28376 |         |          | virtualxid | ExclusiveLock
 28376 |         |          | relation   | AccessShareLock
 28376 | db_name  |          | relation   | AccessShareLock
 28376 |         |          | relation   | AccessShareLock

$ psql -q -c 'select pg_cancel_backend(${process_id})' -d db_name

で、何度切っても直らない・・・・。何故だ

と、テーブル一覧を確認したらちょっとハッとなった

=> \d
                List of relations
 Schema |        Name        |   Type   |  Owner
--------+--------------------+----------+---------
 public | site_categories_id_seq        | sequence | pg-user
 public | sites              | table    | pg-user
(6 rows)

なるほど? xxx_seqというテーブル?の名前は変わっていないっぽい

調べたらテーブルではなくsequenceと呼ばれる何からしい。

mysqlのauto incrementのようなふるまいをするserial型を指定してテーブルを作成すると一緒に作成されるらしい。

なるほど、処理はよくわからんが、こいつの名前も変えてやらないといけないじゃないかなとおもったわけで変える。

=> alter sequence site_categories_id_seq rename to sites_id_seq

これで不具合がなおった!!

参考URL

https://www.postgresql.jp/document/7.3/user/ddl-alter.html

macでpostgresqlを試す

初めて使う

環境

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1611

試す

$ brew install postgresql

文字コードをUTF8で初期化する(?)

$ initdb /usr/local/var/postgres -E utf8
$ postgres --version
postgres (PostgreSQL) 10.1

サーバ起動. あら? プロセスが常駐してターミナルを放してくれない...

$ postgres -D /usr/local/var/postgres

バックグラウンドで動かそうとした

$ nohup postgres -D /user/local/var/postgres &
...
[1]+ Exit 2

あら?

$ postgres -D /usr/local/var/postgres >postgres.log 2>&1 &

これはいけた

$ psql -l

確認できたっぽい

DBの配置箇所をexportしてあげる. .bash_profileに追記する

$ vim ~/.bash_profile
...
export PGDATA=/usr/local/var/postgres

pg_ctlというコマンドがあるらしい。サーバの起動と停止を行う。なるほど。バックグラウンドでやる必要なかったんだ。。。

さっき、起動したのは停止して、このコマンドを使う.

$ pkill -f postgress
$ pg_ctl -D /usr/local/pgsql/data -l /var/log/postgres start
pg_ctl: directory "/usr/local/pgsql/data" does not exist

おろ? 作る

$ mkdir -p /usr/local/pgsql/data
$ pg_ctl -D /usr/local/pgsql/data -l /var/log/postgres start
pg_ctl: directory "/usr/local/pgsql/data" is not a database cluster directory

おろろ?

調べたら初期化コマンドinitdbで起動するっぽい

? じゃあディレクトリを変更すればいい感じなのかな?

$ pg_ctl -D /usr/local/var/postgres -l /var/log/postgres start
waiting for server to start..../bin/sh: /var/log/postgres: Permission denied

ぐぬぬ

$ sudo pg_ctl -D /usr/local/var/postgres -l /var/log/postgres start
Password:
pg_ctl: cannot be run as root

ぬぬぬぬぬ. /var/log/以下でアクセスエラーやな

カレントディレクトリにログを吐くようにした.

$ pg_ctl -D /usr/local/var/postgres -l postgres.log start
waiting for server to start.... done
server started

よし. 起動した.

停止するなら、stopでいいらしい

$ pg_ctl stop

ユーザーの作成はこう.

$ createuser -P pg-user

で、psqlコマンドで作成したユーザーを確認する

$ psql -q -c'select * from pg_user' pg-user
psql: FATAL:  database "pg-user" does not exist

ほう?

さっき作成したDB名を指定しないとダメだった。。。なぜ?

$ psql -d postgres -c'select * from pg_user' `pg-user`

DB作成

$ createdb example-db -O pg-user

コマンドおおいな!

接続

$ psql -U ps-user -d example-db 

\dでテーブル一覧、\lでDB一覧

テーブル作成

=> create table example (
> key char(800) primary key,
> data1 int8
> );
CREATE TABLE

> \d
         List of relations
 Schema |  Name   | Type  |  Owner
--------+---------+-------+---------
 public | example | table | pg-user

> select * from example;
 key | data1
-----+-------
(0 rows)

> \d example
                  Table "public.example"
 Column |      Type      | Collation | Nullable | Default
--------+----------------+-----------+----------+---------
 key    | character(800) |           | not null |
 data1  | bigint         |           |          |
Indexes:
    "example_pkey" PRIMARY KEY, btree (key)

参考URL

qiita.com