読者です 読者をやめる 読者になる 読者になる

技術メモ

業務で調べたこととか...

タブ区切りを置換する

tsv形式で、各行の一部の値を置換したい。
エスケープ周りで少し混乱したのでメモ。

\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)\t\(.*\)/99\t\2\t\3\t\4\t\5\t\6\t\7\t\8/g

指定期間の中で処理を繰り返す

指定期間の中で日付を使ってごにょごにょしたい。

s=`date -d $start_date +%s`
e=`date -d $end_date +%s`
period=`expr \( $e - $s \) / 60 / 60 / 24`

for i in $period # 一日だけの場合は別途調整する必要あり
do
	year=`date +"%Y" -d "$start_date +$i days"`
	month=`date +"%m" -d "$start_date +$i days"`
	day=`date +"%d" -d "$start_date +$i days"`

	# 処理
done



参考
逆引きシェルスクリプト/日付と日付の引き算をする方法 - Linuxと過ごす

IPの個数をカウント

IPレンジの中のIPの個数を知りたい(awkでログを漁る時に必要になったりする)。
IPを2進数と見立てて10進数に変換したうえで差分を取る。

split(ipstart,ipstart_ary,".");
x=ipstart_ary[1]*16777216+ipstart_ary[2]*65536+ipstart_ary[3]*256+ipstart_ary[4]

split(ipend,ipend_ary,".");
y=ipend_ary[1]*16777216+ipend_ary[2]*65536+ipend_ary[3]*256+ipend_ary[4]

cnt=y-x+1

Fuelでトランザクションを張る

FuelPHPで、複数のDBに対してトランザクションを張りたい。

<?phptry {
	$conn = Database_Connection::instance('engine_db');
	$conn_default = Database_Connection::instance('default');

	$conn->start_transaction();
	$conn_default->start_transaction();

	// sql

	$conn->commit_transaction();
	$conn_default->commit_transaction();
} catch (Database_Exception $e) {
	isset($conn) and $conn->rollback_transaction();
	isset($conn_default) and $conn_default->rollback_transaction();
	Log::error($e->getMessage());
}

group単位でまとめて、カンマ区切りの文字列に結合

mysqlでいう「GROUP_CONCAT」をhiveqlでやりたい。
GROUP_CONCAT関数の便利さは異常 - 開発の風景 〜KKZのSE日記〜

この複数行の結果をつなげてカンマ区切りの文字列にしたい場合、GROUP_CONCAT関数が便利です。これを使うとgroup by単位でまとめて、カンマ区切りの文字列に結合してくれます。GROUP_CONCAT内でdistinctやordey byもかけられるので大半の要件は満たせるはずです。



該当する値を配列にまとめる関数を使う。

collect_list(Col)
カンマ区切りで出力される値はユニーク化されない。

collect_set(Col)
カンマ区切りで出力される値はユニーク化される。

※区切り文字を変更したいとき
concat_ws("\t", collect_list(Col))


こんな感じで使う。

SELECT Col1, collect_set(Col2)
FROM your_table
GROUP BY Col1;

// result(tsv)
"col1-1" ["col2-1-1","col2-1-2","col2-1-3"]
"col1-2" ["col2-2-1","col2-2-2","col2-3-3"]
…



参考
LanguageManual UDF - Apache Hive - Apache Software Foundation
hadoop - Column to comma separated value in Hive - Stack Overflow
mysql - Difference between GROUP_CONCAT() and CONCAT_WS()? - Stack Overflow

Androidで開発時かリリース時か判別する

アプリ情報が格納されているクラスを利用して、開発時(デバッグ時)かリリース時かを判別する。
この判別により、開発時とリリース時で処理を振り分けることができる。
例えば、APIキーを開発用とリリース用で分けたり、デバッグログを残したり残さなかったり。

クラスApplicationInfoの中に、アプリの利用状況に応じて値が変動する、変数flagsというものがあるので、

  /**
     * Flags associated with the application.  Any combination of
     * {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
     * {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
     * {@link #FLAG_ALLOW_TASK_REPARENTING}
     * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
     * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
     * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
     * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_SUPPORTS_XLARGE_SCREENS},
     * {@link #FLAG_RESIZEABLE_FOR_SCREENS},
     * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE},
     * {@link #FLAG_INSTALLED}, {@link #FLAG_IS_GAME}.
     */
    public int flags = 0;
    ・・・
    /**
     * Value for {@link #flags}: set to true if this application would like to
     * allow debugging of its
     * code, even when installed on a non-development system.  Comes
     * from {@link android.R.styleable#AndroidManifestApplication_debuggable
     * android:debuggable} of the &lt;application&gt; tag.
     */
    public static final int FLAG_DEBUGGABLE = 1<<1;


こんな感じで、開発用とリリース用で処理を振り分けることができる。

Context appCon = getApplicationContext();
PackageManager pm = appCon.getPackageManager();
ApplicationInfo info = pm.getApplicationInfo(appCon.getPackageName(), PackageManager.GET_META_DATA);

if ((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) == ApplicationInfo.FLAG_DEBUGGABLE) {
	// 開発時(デバッグモード)
}
else {
	// リリース時
}


参考
PackageManager | Android Developers
[Android]マニフェストファイルのapplicationの子要素に<meta-data>を含める。 | 妄想プログラマのらくがき帳
システムプリインアプリの判定 - yu4uの日記
Still Life: Google Playストアからインストールしたアプリか判別する方法

古いAndroidアプリの申請

古いAndroidアプリ(Eclipseで作成)をバージョンアップして申請する際の流れを。

0. GooglePlayDeveloperへの登録

省略

1. 「AndroidManifest.xml」の修正

android:versionCode」「android:versionName」の値を更新する。
外部ツールの認証を開発用とリリース用で分けているのであれば、リリース用のAPIキーに差し替える(GoogleMapsAPIのキーとか)。
そもそも、プログラム側で判断する仕組みをつくっておけという話ではある。

2. apkファイルの作成及び動作確認

apkファイルとは、Androidアプリのプログラム、設定、画像、開発者の署名などが入ったファイルのことです。これがあれば、Androidでアプリを実行することができます。



(apkファイルは作成済みという体で)該当プロジェクトを右クリック[Androidツール][署名アプリケーション・パッケージのエクスポート]を選択する。
表示されるウィンドウにしたがって、Keystore(デジタル署名)のパスとかパスワードとかエイリアスを設定する(同じ内容の署名で作成したapkファイルでないとアップロードできないため、Keystoreとかパスワード等の管理は適切に行う)。
最後に、apkファイルの出力先を指定する(出力先のパスに日本語が含まれているとエラーが出るので気を付ける)。


(該当アプリをインストールしたうえで)実機をPCに接続しADT側に認識されていることを確認する。
apkファイルの出力先でコマンドプロンプトを立ち上げ、「adb install -r ~.apk」を実行する。
実機にapkファイルが読み込まれるので、アプリが起動したら動作確認を行う。

3. アプリの申請

GooglePlayDeveloperにて該当アプリの設定画面を開き、アプリの説明(概要、キャプチャ等)、価格と販売/配布地域を更新したうえで、apkファイルをアップロードする。