さわらブログ

さわら(@xhiroga)の技術ブログ

初めてのsedとawk

会社の若手勉強会でsedawkを勉強した。なんだこれ!めっちゃ便利じゃん!
あとで見返す用にメモ。

sedawkとは

文字列操作に特化したプログラミング言語。シェルから直接実行できて便利!プログラムをファイルとして外部定義することもOK。
文字列をマッチ → 操作 という書き方が共通している。エディタを開かなくても単純なファイル操作ができて嬉しい。

sed

文字列の置換に便利で、例えば空白区切のログをCSVファイルにするときに使ったりするそうだ。

コマンド

$ cat fishlist
Maguro, Tuna
Sake, Salmon
Katsuo, Bonito

$ sed 's/a/A/' fishlist
MAguro, Tuna
SAke, Salmon
KAtsuo, Bonito

sはsubstitute(置換)の略!

便利な使い方

-fコマンドでファイルに定義したsedプログラムを実行できる

$ vi a2A
s/a/A/g

$ sed -f a2A fishlist
MAguro, TunA
SAke, SAlmon
KAtsuo, Bonito

現場では、sedまで含めてシェルスクリプトにする → sed部分だけを外部ファイルにする、という使い方をしてる(発表者談)

パイプで処理を繋げられる

$ cat fishlist | sed 's/a/A/g' | sed 's/o/O/g' | sort

KAtsuO, BOnitO
MAgurO, TunA
SAke, SAlmOn

こういう複数の変換をかますスクリプト書くときって逐次で結果を確認したいと思うんだけど、シェルだとそれが便利にできる!良い! でかいファイルの場合はheadをかませば良さそうだ。

$ head -2  fishlist | sed 's/a/A/g'| sed 's/o/O/g' | sort
MAgurO, TunA
SAke, SAlmOn

catがわり

$ sed '' fishlist
Maguro, Tuna
Sake, Salmon
Katsuo, Bonito

これ役に立つ?笑

エディタを開かなくて良い

sedは入力ファイルを一行づつ処理するので、テキストエディタに全部を読み込む必要がない!素晴らしい!
でかいログの処理に便利そうだ。

awk

CSVのような構造化されたファイルの処理に強い。
ログを一部だけ出力したい時なんかに便利そうだ。

コマンド

マッチ部と操作の組み合わせを渡す。すごいのが、デフォルトで空白を文字列の区切りとして認識してくれること!
だから操作部で$1(マッチ行の一つ目の要素)みたいなことができるのだ。

$ awk '/u/ {print $1}' fishlist
Maguro,
Katsuo,

ちなみに$0で行全体。

$ awk '/u/ {print $0}' fishlist
Maguro, Tuna
Katsuo, Bonito

便利な使い方

-Fオブションで区切文字を変えられる。

$ awk -F ',' '/u/ {print $2}' fishlist
 Tuna
 Bonito

ログ編集で詰んだことがあったんで、現場で使えて便利だなーと思いました。

【棚卸し】匿名関数とラムダ式、クロージャー、カリー化

調べるうちに何となく分かってきたので、自分の言葉で整理。

背景

タイトルに挙げた用語をうまく説明できなかったので調査した。
もし誤りがあれば、コメントで指摘していただけると助かります。

要約

関数がオブジェクトである(=自分のローカル変数を持てる)言語において、関数名を持たない関数を匿名関数 / ラムダ式という。
Javaの場合、抽象化されたメソッドを一つだけもつ「関数型インターフェース」を処理中に継承・クラス化したものを関数オブジェクトのように扱っている。

クロージャーは、自分自身のローカル変数として自分が定義された式の中の変数を参照する関数のこと。定義してくれた式が終了しても変数への参照を持ち続ける=閉じ込める、でクロージャー。
カリー化は、複数の引数をとる関数を一つの引数を取る関数の組み合わせで表現すること。カリーは数学者の名前から取っている。

関数式

JavaScriptでは、関数を定義するために「関数宣言」と「関数式」の二通りがある。後者では関数名を省略することができ、そうしてできた関数は匿名関数になる。
関数式の場合は、定義と同時にその関数を使うことができる。これを即時関数という。

(
  function() {
    console.log("hello");
  }
) ();

クロージャ

理解するまでいろんなブログを参照したが、結局MDNのドキュメントが一番分かりやすかった。
次回からは調べ物はここを真っ先に見るぞ。

クロージャーについて解説しているブログで、誤っていると思われるものがあった。 dqn.sakusakutto.jp

気になったのは、

問題: 呼び出すたびに、1,2,3,...を返すような関数 f( )を定義せよ。
f();  //  1 
f();  //  2
f();  //  3

クロージャを使うと解けるって記事なんだけど、別に使わなくても解けるよね?以下の通り。

f = () => {
  if (typeof x == 'undefined') {
    x = 0;
  }
  x = x + 1;
  console.log(x);
}

どや。

カリー化

どこで見たか忘れたんだけど、良い例があった。

function devisor(x) {
  var devide = (y) => {
    return x/y;
  };
  return devide;
};

half_five = devisor(5)(2);
one_third = devisor(1)(3);

参考文献

関数と関数スコープ - JavaScript | MDN

クロージャ - JavaScript | MDN

アロー関数 - JavaScript | MDN

クロージャ - Wikipedia

WASのディレクトリ構成

現場で学んだことの棚卸し。

背景

WAS(WebSphere Application Server)を使っていると、トラブルが起きた時にディレクトリ構成の知識が必要になってくる。
せっかくどのディレクトリにどんな役割があるか少し知ったので、自分の言葉で整理する。
いずれもWindowsが前提。

ディレクトリ構成

RAD(Rational Application Developper)のインストール・ディレクトリー以下、
runtimes¥base_v7¥profiles¥{プロファイル名} を参照。*WAS7の場合

bin

startServer.bat, stopServer.batがある。普段はRADから直接起動しているが、WASはコマンドラインから起動できる。
メモリが少ないマシンで開発していると、eclipseを立ち上げずにサーバーを起動したい局面で重宝しそう(ほんとに2017年かよ...)

config

サーバーの設定ファイルがあり、管理コンソールの設定内容が反映されている。
config¥cells¥{cell名}¥nodes¥{node名}¥servers¥{アプリケーションサーバー名}/server.xml

Tomcatの場合はconf直下にある。
{tomcat}¥conf¥server.xml

installedApps

サーバーをサーバー上のリソースで実行している場合、ワークスペースからコピーしたクラスファイルが配置されるフォルダ。
Tomcatの{tomcat}¥webapps に当たると思われる。
ソースの修正がどうしても反映されない時に、クラスファイルを強引に置き換えて直したい時などに使う(そんなことあるのか)

logs

サーバー起動時のログがある。ここを確認してOutOfMemoryだったら、JVMのヒープサイズを大きくする(その前に、同時に起動しているプロセスを減らす)
logs¥{アプリケーションサーバー名}以下、server.log など。

temp

JSPのクラスファイルがある。サーバーを再起動し、かつブラウザをスーパーリロード(キャッシュを無視した再読み込み)してもJSPファイルの変更が反映されない場合、このフォルダの対応するクラスファイルを削除するとよい。
Tomcatの場合、{tomcat}¥workにある。

行値構成子とテーブル値構成子:なぜSELECT結果を直接INSERTしたり、WHERE句で複数列を同時に比較できるのか

背景

現場で見かけてもやもやしていたSQLに、次のようなものがある。

INSERT INTO my_db.animals SELECT * FROM your_db.animals; --例1.

SELECT結果を直接INSERTしている。INSERT文と言えば INSERT INTO xxx VALUES xxx の形式だと思っていたので驚いた。
同時に、今までINSERT文の文法だと思っていたものが全てじゃないような気がしてきた。

こんな例もある。

SELECT * FROM my_db.animals WHERE (name, sound) = ('Cat', 'Myao'); --例2.
SELECT * FROM my_db.animals WHERE (name, sound) IN SELECT name, sound FROM your_db.animals; --例3.

WHERE句の左辺が複数要素ある。これは便利だ。
もし左辺に1項目づつしか指定できなかったら、例3.では比べる対象の列を項目に合わせて分けるため、SELECTを2回発行することになってしまう。

どうして例1.〜 例3.のような文法が使えるのか、ちょっと調べてみた。

前提

SQLの言語仕様はISOで定められており、これに各ベンダーが準拠している。
歴史的に統一標準規格がなかった時期が長かったため、ベンダーによって準拠の度合いはまちまちなんだそうだ。(Wikipediaより)
したがって、ISO(制定年ごとにバージョンがある)があればそれを参照し、ISOのドキュメントがなかったりベンダー固有仕様ならベンダーのサポートサイトを参照しよう。

これから調べることは文法の基本っぽい雰囲気だし、何よりISOのドキュメントが見つかったのでそれを読んで理解しよう。

行値構成子とテーブル値構成子

ぶっちゃけ自分で考えたことで事実確認はしてないんだけど、どうして例1. 〜例3. の文法が使えるのかの結論から行こう。
- INSERTが値に取るのはテーブル型の無名オブジェクトと思われる。VALUESはテーブル型のオブジェクトを生成するコンストラクター(テーブル値構成子)にすぎない。
- WHERE句では左辺が行値構成子の場合、右辺に対応する列があるものとして要素ごとに評価する。

それでは、行値構成子とテーブル値構成子とは何なのか。
SQL92の規格によれば以下の通り。
※例示と訳語のチョイス、翻訳は私自身によるものです。


row value constructor(行値構成子、行値コンストラクタ、RVCとも。)
値のセットを行または行の一部を構成するようにするもの。

('Cat', 'Myao') -- 行値構成子
('Dog') -- これも行値構成子
'Lion', 'Gyaoo' -- ()で囲わない場合、行値構成子リスト
'Beer' -- 単体だと行値構成子エレメント

要するに、()で囲うとそこが行として見なされるわけだな。

table value constructor(テーブル構成子、テーブル値コンストラクター、TVCとも。)
行値構成子をテーブルを構成するようにするもの。

VALUES ('Cat', 'Myao'), ('Dog', 'Bao'), ('Bird', 'Piyo') -- テーブル構成子

ということは、こんなこともできるのである。

SELECT * FROM ( VALUES('Cat', 'Myao'), ('Dog', 'Bao'), ('Bird', 'Piyo') ); -- VALUESを使い、手打ちの値をテーブルに見立てる。  
VALUES(1); -- 1をSELECTで取得したテーブルと同じように見立てる。

いや〜知らなかった。

まとめ

INSERT文は必ずVALUESを使わなければいけないのではなく、値がテーブル型のオブジェクトなら良さそうだ。
こういう例は他にもありそうだから、SQLを使う時は何のオブジェクトを扱っているのか気にしてみよう。

参考文献

SQL - Wikipedia
そもそもSQLについて調べるにあたり、何を見ればいいか分からなかったので。

http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
Wikipediaのリンクから発見した、SQL 92の仕様書。カーネギーメロン大学のサーバーに置いてくれてあるようだ。

テーブル値コンス トラクター (TRANSACT-SQL) | Microsoft Docs
T-SQLMicrosoftによるSQLの規格)のドキュメント。

SQL Server 2008 から記述が短くなったもの の紹介 - お だ のスペース
個人ブログ。テーブル値構成子の使い方が例示されており、分かりやすい!

i am BEST : VALUES コンストラクタは必ずしも INSERT INTO とだけ用いられるわけではない!?
上に同じく。

sqlのwhere in って、複数条件(カラム)を指定できるんですね - end0tknrのkipple - web写経開発
上に同じく。

【備忘録】iBatis、log4j、依存性注入

現場で使っていて理解したことの棚卸し。

iBatis

JavaのO/Rマッパー。
勘違いしていたが、iBatisとDAOオブジェクトは直接関係ない。
iBatisは「if文などでカスタマイズ可能なSQLを」「入出力のパラメータをDTOオブジェクトにまとめてマッピング可能にし」「JDBCを意識しないで発行する」ためのライブラリーである。そうした機能は、iBatisが提供するsqlmapインスタンスのメソッドから利用可能。
ただし、アーキテクチャの問題として、SQLDTOオブジェクトをマッピングしたXMLファイルごとにデータアクセスのためのオブジェクト(内部でsqlmapインスタンスを使用)を定義することは考えられる。
そのせいでiBatisとDAOが依存していると勘違いしていた。

SqlMapConfig.xmlの設定を読み込み、アプリケーション内で一つだけのインスタンスを持つ(これは強制ではなくパターンの問題かも?)ただし、複数のDBにアクセスできるよう、SQL発行に使用するコネクションはアプリケーション起動後に変更可能である。
使用するSQLはSqlMap.xml内に定義するが、複数のXMLファイルに分散して記載することもできる。

普段生のSQLを触るので、PythonでSQLAlchemyを触った時よりも使いやすかった(そちらはSQL文をプログラマが設定することはなく、代わりに基本のSQLに相当するメソッドを組み合わせて利用する)

log4j

Javaはじめクロスプラットフォームで使用できるログ出力ライブラリー。
ログの重要度や出力先、形式を属性として持つLoggerインスタンスをアプリ内で生成し、ログを出力させる。
出力先、形式をそれぞれAppenders、Layoutsクラスとして定義しており、複数のLoggerインスタンス間で共有できる。
ログの出力先となるフォルダとその識別のためのIDをクラスパス直下のlog4j.xmlで管理しており、これをよく忘れて先輩に聞く(ログ出るのどこでしたっけ?)

依存性注入

クラス内で他のクラスのインスタンスが必要なときに、受け入れる変数の型をインターフェースで宣言し、肝心のインスタンスを呼び出し元に作らせたり、DIコンテナに作らせたりするパターンのこと。
他のクラスを直接参照しないことで、そのクラスのソースが完成していない状態でコンパイルをしても怒られないで済む。なので、複数人でプログラミングしているときに作業順を気にしないでよくなるそうだ。
(1機能のDelegateとServiceとDAOを別人がプログラミングすることってそんなにない気もするけど...逆に言えば部品の共有が進んでいないってことでもある。)
他にも、テストや開発環境の場合だけ参照する実装クラスを変えることが、ソースの修正なしにできる。これは嬉しいかも。

実装を見るとイメージが掴みやすいと思う。例はWikipediaより、DIコンテナを使った場合。

public static void main(String[] args) {
        IAutomatedStockTrader stockTrader =
            (IAutomatedStockTrader) DependencyManager.create(IAutomatedStockTrader.class);

参考資料

iBatis

iBATIS2/iBATIS3/mybatis各種アーカイブ・ドキュメント一覧 - Shinya’s Daily Report

log4j

Apache log4j 1.2 - Short introduction to log4j

依存性注入

依存性の注入 - Wikipedia

DI・DIコンテナ、ちゃんと理解出来てる・・? - Qiita

【備忘録】eclipseのエンタープライズ・アプリケーション・プロジェクトについて

eclipseのプロジェクトが何なのかしっくり来ていなかったので。

背景

現場でプロジェクトがサーバーに追加できない状態になり、解決策を調べるうちに「そもそもプロジェクトとは?」「もっと言うと、Java EEとは?」って状態になったので。

Java EEとは

Webアプリケーションの作成に役立つJava標準のライブラリ群。   サーバ・アプリケーション間のインターフェースであるServletPythonだとWSGI)、テンプレートエンジンのJSPPythonだとJinja2他)等々がある。   それだけでなく、アプリケーションサーバーが複数のアプリケーションを一つのアーカイブとして扱うための形式を定義している。その際のアーカイブがEARファイルである。

eclipseのプロジェクトとは

eclipseが複数のソースコードをデプロイやバージョン管理のための一つの単位として扱うためのフォルダ。
ただのフォルダではなく、離れたフォルダのリソースを参照するように設定することができる。

中でもJ2EE(Java EEの古いバージョン)で定義したディレクトリ構成に対応するフォルダをJ2EEモジュール・プロジェクトと称するようだ。
それらJ2EEモジュール・プロジェクトを一つのアーカイブとして扱うため、EARファイルの雛形となるのがエンタープライズ・アプリケーション・プロジェクトである。

エンタープライズ・アプリケーション・プロジェクトとプロジェクト・ファセット

J2EEに準ずるアプリケーションはxmlファイルにそのための設定を持つ(と思う、実際には見ていない...。)こうした設定を、GUIベースでプロジェクトに対する特性として設定できるのがeclipseのプロジェクト・ファセットである。
EARファイルの作成には親のエンタープライズ・アプリケーション・プロジェクトと、子のJ2EEモジュール・プロジェクト(特にサーバーに追加する場合は動的Webモジュールプロジェクト等)が必要になる。
こうした定義はプロジェクト・ファセットで行う。
モジュール間の依存関係は、本来はEAR > META-INF > application.xmlで設定する。eclipseの場合はプロジェクトのプロパティからJ2EEモジュール依存関係で設定可能。

プロジェクト・ファセットの特性のバージョン関係は依存性があるので、うまくプロジェクトが追加できないことがあれば設定を見直すべし。

その他現場で役立つこと

ソースの修正が反映されない場合、クラスファイルが再作成されていないか再デプロイされいていないかのいずれか。
前者の場合はクリーンビルド(クラスファイルを自動削除後にビルド)後者の場合はクリーンデプロイ(サーバーが参照するディレクトリ上のクラスファイルを削除してデプロイ)が効果あり。もちろん手動で消しても効果は同じ(ビルドし忘れなければ)

参考資料

Help - Eclipse Platform eclipse公式ドキュメント

IBM Knowledge Center IBMeclipse関連ドキュメント。↑の日本語訳があると考えてよさそう。

いまさら聞けないサーバーサイドJava 第1回 これだけは知っておきたいJ2EEの基本 | 技術トピックス | ウルシステムズ株式会社

【備忘録】Struts1系で調べたことまとめ

2017年にStruts1系を記事にしている人がいること自体がすごい?

背景

Struts1系を使ってアプリを作る機会があり、1画面を追加するに当たって調べたことの棚卸し。

調べたこと。

  • アクセスパスごとに呼び出されるActionを変更するには<action-mapping>のtype属性を指定する。
    validationが働くとimportで指定したページに遷移する。
    pathには.doを含めなくても構わない。web.xmlでそう設定してあるようだ。以下を参照。
    stackoverflow.com

  • actionクラスが受け取るformは、action-mappingのname属性<form-bean>のname属性/type属性の二段構えで設定する。

  • action後にフォワードする遷移先はaction-mappingの<forward>タグで指定する。<global-fowards>よりもそちらが優先。
  • Tilesの設定では、大枠となるファイルは<definition>タグのpath属性/extends属性で指定する。pathではjspファイルを指定するのに対し、extendsではTilesで作成したテンプレートの名前を指定する。
  • 上記<action-mapping>, <global-foward>, <form-bean>などは個別の.xmlファイルで管理できる。それぞれ複数あっても構わない。

まだ分からないこと

  • 各種xmlファイルがどこに配置されているのかの法則がよく分からない。
  • JSP内でJavaScriptCSSを指定する際のやり方が複数あるようだ。

参考資料

www.amazon.co.jp
まずはこの本を読んで調べる。

Index of /dist/struts/documentation
Struts1系はサポート終了しているが、Apacheのホームページからドキュメントを入手可能。そのリンク。