Java 正規表現を使ってUser-Agentから端末型番を簡単に取得する(ガラケー編)

## はじめに
今は昔、の話ですが、応用すれば現代の端末にも使えると思います。

User-Agentの文字列中の端末型番の位置を正規表現でグループ化しておき、
java.util.regex.Matcherクラスを使って該当のグループの文字列部分だけを取得します。

なお、1点ご了承いただきたいのですが、
すでに存在しないキャリア名もありますし、
一部の端末のオプショナルなブラウザまではケアできていません(WILLCOMのOperaなど)。

事前に準備する外部ライブラリ等はありません。
java.util.regex.Matcherクラス、およびjava.util.regex.Patternクラスを使用します。

## 実装例
サンプルでは、動作確認しやすいようにmainメソッドで実行できるようにしてあります。

```java:UserAgentTest.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author tool-taro.com
 */
public class UserAgentTest {

	public static void main(String[] args) {

		//型番を取得したいユーザエージェントのリスト
		String[] sources = {
			"DoCoMo/2.0 F900i(c100;TB;W22H12)",
			"UP.Browser/3.04-SN12 UP.Link/3.4.4",
			"KDDI-HI31 UP.Browser/6.2.0.5 (GUI) MMP/2.0",
			"J-PHONE/5.0/V801SA/SN123456789012345 SA/0001JP Profile/MIDP-1.0 Configuration/CLDC-1.0 Ext-Profile/JSCL-1.1.0",
			"MOT-V980/80.2F.2E. MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1",
			"Vodafone/1.0/V705SH/SHJ001[/Serial] Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1",
			"SoftBank/1.0/831SH/SHJ003/SN123456789012345 Browser/NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1",
			"Mozilla/3.0(WILLCOM;KYOCERA/WX340K/2;3.0.3.11.000000/1/C256) NetFront/3.4",
			"emobile/1.0.0 (H11T; like Gecko; Wireless) NetFront/3.4"
		};

		/*
			各キャリアの正規表現(型番判定に不要な部分はあいまいさを残し予期せぬアンマッチを避けています)
			docomo   ^DoCoMo/\d+\.\d+[ |/]{1,}([a-zA-Z0-9_\+\-]+).*$
			au       ^UP\.Browser/[\d\.a-z]+-([a-zA-Z0-9]+) .+|KDDI-([a-zA-Z0-9]+) UP\.Browser/[\_\d\.a-zA-Z]+ \(GUI\) .+$
			SoftBank ^J-PHONE/\d+\.\d+/([a-zA-Z0-9_\-]+).*|Vodafone/\d+\.\d+/([a-zA-Z0-9_\-]+).*|SoftBank/\d+\.\d+/([a-zA-Z0-9_\-]+).*|MOT-([a-zA-Z0-9_\-]+)/.*$
			WILLCOM  ^Mozilla/[\d\.]+\(WILLCOM;[a-zA-Z0-9\-_]+/([a-zA-Z0-9\-_]+)/.+\).+$
			emobile  ^emobile/[\d\.]+ \(([a-zA-Z0-9_\-]+); .+\).*$
		 */
		//上記をまとめたパターンの集合体
		String patternString = "^DoCoMo/\\d+\\.\\d+[ |/]{1,}([a-zA-Z0-9_\\+\\-]+).*"
				+ "|UP\\.Browser/[\\d\\.a-z]+-([a-zA-Z0-9]+) .+"
				+ "|KDDI-([a-zA-Z0-9]+) UP\\.Browser/[\\_\\d\\.a-zA-Z]+ \\(GUI\\) .+"
				+ "|J-PHONE/\\d+\\.\\d+/([a-zA-Z0-9_\\-]+).*"
				+ "|Vodafone/\\d+\\.\\d+/([a-zA-Z0-9_\\-]+).*"
				+ "|SoftBank/\\d+\\.\\d+/([a-zA-Z0-9_\\-]+).*"
				+ "|MOT-([a-zA-Z0-9_\\-]+)/.*"
				+ "|Mozilla/[\\d\\.]+\\(WILLCOM;[a-zA-Z0-9\\-_]+/([a-zA-Z0-9\\-_]+)/.+\\).+"
				+ "|emobile/[\\d\\.]+ \\(([a-zA-Z0-9_\\-]+); .+\\).*$";

		//判定処理
		Pattern pattern = Pattern.compile(patternString);
		Matcher matcher;
		String result;
		for (String source : sources) {
			result = null;
			matcher = pattern.matcher(source);
			if (source.matches(patternString) && matcher.find()) {
				//matcher.groupCount()はパターン数を返す(この例では9種類あるので"9"が返る)
				for (int i = 0; i < matcher.groupCount(); i++) {
					/*
						matcher.group(0)は、マッチした文字列全体を返す
						例: "DoCoMo/\d+\.\d+[ |/]{1,}([a-zA-Z0-9_\+\-]+).*"にマッチする"DoCoMo/2.0 F900i(c100;TB;W22H12)"
						
						matcher.group(1)以降は、パターン内に()で指定されたグループにマッチした文字列を部分的に返す
						例: "([a-zA-Z0-9_\+\-]+)"にマッチする"F900i"
					 */
					if (matcher.group(i + 1) != null && !(matcher.group(i + 1)).equals(source)) {
						result = matcher.group(i + 1);
						break;
					}
				}
				//標準出力
				System.out.format("判定 %1$s\n→%2$s\n", source, result);
			}
		}
	}
}
```

## 動作確認

```
$ UserAgentTest.java
$ java UserAgentTest
$ 判定 DoCoMo/2.0 F900i(c100;TB;W22H12)
→F900i
判定 UP.Browser/3.04-SN12 UP.Link/3.4.4
→SN12
判定 KDDI-HI31 UP.Browser/6.2.0.5 (GUI) MMP/2.0
→HI31
判定 J-PHONE/5.0/V801SA/SN123456789012345 SA/0001JP Profile/MIDP-1.0 Configuration/CLDC-1.0 Ext-Profile/JSCL-1.1.0
→V801SA
判定 MOT-V980/80.2F.2E. MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1
→V980
判定 Vodafone/1.0/V705SH/SHJ001[/Serial] Browser/VF-NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1
→V705SH
判定 SoftBank/1.0/831SH/SHJ003/SN123456789012345 Browser/NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1
→831SH
判定 Mozilla/3.0(WILLCOM;KYOCERA/WX340K/2;3.0.3.11.000000/1/C256) NetFront/3.4
→WX340K
判定 emobile/1.0.0 (H11T; like Gecko; Wireless) NetFront/3.4
→H11T
```
それぞれの型番を取得できました。
久しぶりに見る型番ばかりで懐かしくなりました。
## 環境
- 開発
	- Windows 10 Pro
	- JDK 1.8.0_112
	- NetBeans IDE 8.2

- 動作検証
	- CentOS Linux release 7.2
	- JDK 1.8.0_112

Webツールも公開しています。
[Web便利ツール@ツールタロウ](http://tool-taro.com/)