Javaで.【ドット】でsplitしたい

お久しぶりです。ゼネットの阿部です。

Javaでの文字列分割で.【ドット】を使ったところうまく行かなかったので、備忘録として記載します。

"北海道,青森,...,沖縄"のようにカンマ編集されている文字列を分割したいということはよくあると思います。

Javaを利用されている方はすぐに思いつくと思いますが、

String[] cities = "北海道,青森,...,沖縄".split(",");  
for(String city : cities){
  System.out.println(city);
}

とすることで

北海道
青森
・
・
・
沖縄

と配列に分割されます。

ここで、文字列が"北海道.青森.,,,.沖縄"のように.【ドット】で分割されている場合に、カンマの場合と同様に処理させます。

String[] cities = "北海道.青森.,,,.沖縄".split(".");  
for(String city : cities){
  System.out.println(city);
}

とすると例外が発生

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

あれ?分割がうまく行っていない?

ということでOracleDocで調べました。*1

splitの概要には

【この文字列を、指定された正規表現に一致する位置で分割します。】

と記載されていました。

どうやら文字列の.【ドット】が正規表現として判断されたためいずれの文字にも一致しなかったため、分割されていないようだとわかりました。

インターネットで調べてみると、文字を正規表現として意味を持たない文字に変換するためには、

Pattern.quote(".")

とする必要があるとわかりました。

String[] cities = "北海道.青森.,,,.沖縄".split(Pattern.quote("."));  
for(String city : cities){
  System.out.println(city);
}

とすることで

北海道
青森
・
・
・
沖縄

と分割できました

引数で与えた文字が【意味を持たない】文字として利用されるか【正規表現】文字として扱われるのかをしっかり理解しなければ行けないと気付かされた一件でした。

ちなみに余談ですが、

Pattern.quote(".")

の戻り値は

\Q.\E

でした。 これについてはまた今度調べて見たいと思います。

*1:*昔のJavaDocです

追従型メニューの作り方

システム事業部の五十島です。

今回は追従型メニューについて説明していきたいと思います。
追従型メニューとは、スマホサイトでよく見る『スクロールしても画面上に表示されているメニューや広告など』になります。
ちょっと難しそうと思うかもしれませんが、簡単なCSS・HTMLとちょっとだけ頭を使うJSで作れてしまいます。

htmlとCCSは以下のようになります。
構造はシンプルで、idが#init_button#button_down_areaのボタンは最初から表示させておいて、 両方が画面上から見えなくなったら、スクロール用のボタン(.scroll_button_area)を表示させるというものです。

<!-- 初期表示のボタン -->
<button id="init_button">スクロールするボタン</button>

<!-- 実際にスクロールするボタン -->
<div class="scroll_button_area">
  <button>スクロールするボタン</button>
</div>
<div style="height: 500px">
  <!-- スペースを開けるためのタグ -->
</div>

<!-- ボタンのスクロール終了位置 -->
<div id="button_down_area">
  <button>スクロールするボタン</button>
</div>
.scroll_button_area {
  display: none;
}

.show_scroll_button {
  display: block;
  position: fixed;
  bottom: 0px;
  left: 0px;
  width: 100%;
  padding: 0px;
  background-color: #ffffee;
}

JSは以下のようになります。
表示している位置の情報を取得して、div.scroll_button_areaに表示させるクラスを追加して、制御しています。

$(document).ready(function() {
  $(function() {
    $(window).on('scroll', function() {
      var topBtn = $('#init_button');

      // ボタンが表示されていない
      if (!topBtn.size()) { return ; }

      // スクロール中のボタン表示
      var scrollArea = $('.scroll_button_area');

      // 開始位置、終了位置の取得
      var startLine = topBtn.offset().top;
      var endLine = $('#button_down_area').offset().top;

      // 表示画面領域の座標取得
      var scrollTop = $(this).scrollTop();
      var scrollBottom = scrollTop + window.innerHeight;

      // 上部ボタンが画面から非表示、
      // 下部ボタンが画面上に表示されるまで
      if ( scrollTop > startLine && scrollBottom <= endLine ) {
        scrollArea.addClass('show_scroll_button');
      } else {
        scrollArea.removeClass('show_scroll_button');
      }
    });
  });
});

offset()メソッドで、画面全体のどの位置に各ボタンがあるのかを取得します。
ScrollTop()window.innerHeightメソッドで表示領域の上下の座標を取得し、 22行目で各ボタンが表示領域に存在しているかを判定しています。
各ボタンが表示領域外の場合はスクロール用のボタンを表示し、それ以外の時は非表示という制御を行なっています。

JSを改良すれば、表示・非表示のタイミングを好きに変更できるので、改良して使って見てください。

RailsからRDS(MySQL)のDBに接続できなかった話

こんにちは。システム事業部の大柳です。

Rails+MySQLな構成でEC2にデプロイしたときに、DBにつながらず苦戦したので状況と解消方法を書き留めます。

システム構成

  1. Ruby: ver2.4.2

  2. Rails: ver 5.1

  3. MySQL: ver 5.6 (Amazon RDS)

状況

ソースをクローンしてきて、bundle install してrails s で起動を行うところでした。

起動してみると

Mysql2::Error - Access denied for user '******'@'*****' (using password: YES):

どうやらパスワードが間違っているようです。

database.yml をみなおしてみました。

production:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  pool: 5
  host: <%= ENV['DB_HOST'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: <%= ENV['DB_PASSWORD'] %>
  database: <%= ENV['DB_DATABASE'] %>

ENV['XXXX'] とかは環境変数に定義してあるのを拾ってきます。

環境変数を確認してみましたが、ちゃんと設定されていました。

exec $SHELL --login で反映し直しましたがだめでした。

そこで試しにmysqlコマンドでつながるのか試しました。

mysql -u USER -h HOST -p DATABASE

すると

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 233893
Server version: 5.6.39-log MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

つながりました・・!

以上のことからrails側のDBの設定がどこかしらおかしいことがわかりました。

その後いろいろ試してはみたものの原因が全然わからず・・・・

上司や同僚に電話して助けを乞ったところ

「わかったよ」

!!!

解決したdatabase.ymlがこちら

production:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  pool: 5
  host: <%= ENV['DB_HOST'] %>
  username: <%= ENV['DB_USERNAME'] %>
  password: "<%= ENV['DB_PASSWORD'] %>"
  database: <%= ENV['DB_DATABASE'] %>

結論をいうと、原因はパスワードに「#」が含まれていたためでした。

「#」が含まれていると何がだめなのかというと、yamlファイルのきまりで「#」以降が コメントアウト になります。

つまり「#Password」というパスワードだっとするとrails''空文字と認識します。

そりゃあ何度やってもパスワードが間違っていると怒られるわけです・・・。

超初歩的な問題でした。

次回からは気をつけたいと思います。

SECCON 2018 Online CTF Writeup

お久しぶりです。ゼネットの阿部と申します。 ブログを書くのはかなり久しぶりです。

SECCON2018に参加し、チームとしては合計点203点という悲しい結果に終わりました。

なんとか1問解けたので、紹介しようと思います。

私が担当したのは f:id:zenet-tech:20181029103342p:plain の問題です。

以下のファイルのダウンロードとFLAGを入力するというだけで特段説明もなく、 SECCONにチャレンジするのが始めての私はもう分けがわかりませんでした。 【unzip.zip_26c0cb5b40e9f78641ae44229cda45529418183f】

しかし、始めなければしょうがないということで始めました...

【unzip.zip_...】というファイル形式で、問題もunzipだったので、 拡張子を【.zip】に変えてみて、展開したらどうかと試したところ以下のフォルダに展開されました。 f:id:zenet-tech:20181029103910p:plain

makefile.sh】を見てみると、

echo 'SECCON{'`cat key`'}' > flag.txt
zip -e --password=`perl -e "print time()"` flag.zip flag.txt

どうやら環境変数のkeyをflag.txtに書き込んでそれをzip化しているようです。

ということは、

zip -e --password=`perl -e "print time()"` flag.zip flag.txt

でパスワードに設定している

perl -e "print time()"

がzipのパスワードで、これさえわかれば解けるはずだと思いました。

Perlはほぼ触れていなかったので、インターネットで検索するとPerlでシステム日時を取得し秒変換をしていることが分かりました。

今回のSECCONは 2018/10/27 15:00:00開始だったので

① 【2018/10/27 15:00:00】を秒に変換して【1540620000】で解凍を試みるも失敗。

UTCが原因かと思い、

② 【2018/10/27 6:00:00】【1540534242】で解凍を試みるも失敗。

日時が知りたいと思い、flag.zipのプロパティを開くと f:id:zenet-tech:20181029105030p:plain

このzipファイルが2018/10/27 0:10:42に作られていることがわかりました。

そこで、

③ 【2018/10/27 0:10:42】【1540566642】で解凍を試みるも失敗...

もしかしたら、ファイルのパスワードを取得したタイミングとファイルが生成されたタイミングがずれたのではと推測し、

④ 【2018/10/27 0:10:41】【1540566641】で解凍を試みると成功!!!

所要時間は【40分】ほどで、難易度も低かったため、もともと500点だった得点も【101点】に... まあ解けただけでも良しとしました。なかなか楽しかったです。

来年はもう少し準備をして、時間も確保してから参加しようと思いました。

ISUCON8予選に参加しました!

こんにちは!システム事業部の村田です。

先日開催されたISUCON8予選に、他の社員2名とチーム「ポテチはのり塩派」で3人で初参加しました!

結果としては予選敗退で、再起動試験でfailという悲しい結果・・・でした

最終的なベンチスコアは6894でした

f:id:zenet-tech:20180927182424p:plain

役割としては 私:インフラ 他2人:コード という形で進めました。

そこまでの作業をまとめようと思います。

続きを読む

RubyKaigi2018参加レポート パート2

はじめまして。システム事業部の大柳です。

だいぶ時間がたってしまいましたが、5月末にRubyKaigiに参加したので印象に残った講話と感想のレポートを書きたいと思います。

はじめに自己紹介

  1. 入社5年目

  2. Ruby歴:約1年

  3. 仕事:Ruby on Rails を使ったシステム開発

以前は主にJavaを使ってシステム開発を行っていましたが、上記のようにRuby自体は初めて間もないひよっ子です。

経験は浅いですがとても有意義な時間となりました。

以下は印象に残ったセッションです。(他の人の記事と被っている部分もありますがご了承ください。。)

セッション

Proverbs

Matzことまつもとゆきひろ氏のセッションです。 「名は体を表す」ということわざがあるようにプログラミングにおいて名前をつけることは重要だというお話です。 何をしたいかがわかるようなメソッド名を付けたり、何を保持しておきたいかわかるような変数名を付けることで誰が見ても理解がしやすくなります。 経験上、例えばユーザーのIDを取得しているのに代入した変数名がただの user になっているなんてことはよくありました。(本当はuser_idとかが良い) こういったことを避けるためにも名前は十分考慮して付けたいですね。

Ruby Committers vs the World

RubyCommitterの方々が登壇していくつかのトピックについて議論や意見を言い合う場です。 中でも気になったのはRuby2.5で実装予定の新機能について「Endless Range」というのが実装される話です。 RubyにはRangeクラスという範囲を扱うクラスがありますが、今まではlastに無限大を指定する際にFloat::INFINITY とかを指定する必要がありました。

しかし今回の機能で範囲のlastの省略が可能になります。 Railsで使うことはあまりない気がしていますが、便利だなと思いました。 というのと同時に今まではlastの書き忘れでsyntaxエラーで落ちてたところが無限にループされる事象が発生しそうな気がしました。

TRICK 2018 (FINAL)

TRICKとは Transcendental Ruby Imbroglio Contest for RubyKaigi の略でRubyKaigi恒例の<めちゃくちゃだけどめっちゃすごいコード>コンテストです。 印象に残ったのは以下のtompngさんのコンテンツです。 Merry Christmasという白抜きのコマンドを実行すると3Dレンダリングされたクリスマスツリーが表示されるプログラムです。

最も歓声が上がってた気がします・・! 他にもさまざまな奇想天外だけどすごいコードがあり、Rubyでこんなことできるのか、、と驚かされました。 ちなみにこのTRICKは今回がFinalだったみたいで次回開催は予定されてないそうです。ぜひ復活してほしいですね!

懇親会

RubyKaigiでは全公演が終了したあとに、After Partyなる懇親会があります。 多くのRubystたちと食事をしながら交流できる場でRuby界隈で有名なコミッターともお話ができるチャンスがあります。

私もいくつかの懇親会に参加しましたが、最初はどのようにして会話に参加すれば良いのかわからずおろおろしてしまいました。 しかし何人かの方から話しかけられたりして会話してるうちに自分からも声をかけていろんな方の話を聞くことができました。 2日目は株式会社オプトさんのドリンクアップに参加し、仙台のおいしい料理をいただきました! 業界あるある話ができたりして楽しめました。ありがとうございました。

1日目f:id:zenet-tech:20180818163704j:plain 2日目f:id:zenet-tech:20180818165603j:plain

最後に

今回初めてRubyKaigiに参加することになり、はじめは自分なんかがセッションを聞いて理解ができるのか?未熟者が参加して失礼じゃないか?と不安もありました。 正直なところ内容は難しいものばかりで今の自分に有益となるかは微妙なところでした。。 しかし、RubyKaigiの魅力は難しいすごい人達のお話を聞くことだけはないと思っています。

上記にも記載しましたが、RubyKiagiではRubystたちと交流ができる場でもあります。 自分と同じ技術を使って仕事をしている方たちと交流できるのは自分にとってすごく刺激になりました。 これからもっと勉強して技術を身に着け、RubyRailsを使いこなせるように頑張っていきたいと思いました。 経験が浅い方でも参加して決して損はないのでどんどん参加してほしいです。

来年は福岡で開催ということが決まりました。ぜひ次回も参加したいと思います!!

RPAセミナー参加レポート

お疲れ様です。第1事業部の西槇と申します。 初めての投稿ですので拙い文章になるかと存じますが、最後まで読んでいただけると幸いです。 (写真をあまり撮れていなかったので、文章が多めです….)

はじめに、私の自己紹介をいたします。ゼネットに入社してから2年目の、まだまだひよっこな文系SEです。様々な現場を見てきた経験を生かして仕事が出来るよう、日々努力しております。ちなみに好きな食べ物は酸辣湯麵です。

今回私は、話題沸騰中の「RPA」について理解を深めるべく、6/22(金)に行われたセゾン情報システムズ様主催の「業務自動化RPAセミナー」に参加いたしました。5名の講演者の講義を拝聴しましたが、どの講義も内容が濃い上にとても分かりやすく、よりRPAについて理解する事が出来ました。全ての講義についてお話ししたいところですが、今回は特に印象に残った講義を取り上げたいと思います。

「RPA」とは?

まずは、本題に入る前に「RPA」とは何かを簡単にご説明したいと思います。RPAとは、「Robotic Process Automation」の略称で、2016年頃から徐々に注目されてきているキーワードの一つです。この言葉には、広義的な意味と、狭義的な意味とで異なる2つの意味を持っています。 前者は、「ソフトウェアロボットによるホワイトカラー業務(データ入力/集計業務など)の自動化」の事を指します。一方後者は、広義的な意味での「RPA」の中のクラス*1の一つを指し、「定型業務を自動的に処理することが出来るソフトウェアロボット」を指します(RPAは後者の意味でよく使われています)。 私も以前、ソフトウェアロボットとしてのRPAの導入に関わる業務を経験しましたが、多数部署へのRPA導入計画などもあり、RPAに大きな期待を抱いている事が現場からもひしひしと伝わっていました。

RPAセミナー講義について

それでは、次にRPAセミナーの感想についてお話いたします。 特に印象に残ったのは、『日立グループのRPA活用事例と、その経験から学ぶRPAとの上手な付き合い方』についての講義でした。講義ではRPA導入が上手く進まない企業が多い現状と、そのような状況に陥ってしまう要因と対策を、実例を用いてお話しいただきました。 その中でも「RPAと他ツールを組み合わせ、適材適所で活用する事によって高い保守性を実現させる」というお話がとても興味深かったです。今まで、RPAのみを使用した自動化業務の実例しか見た事がなかったため、今回の講義によって自分の中の自動化に対する選択肢がより広くなったと感じました。 f:id:zenet-tech:20180816131827j:plain (RPAセミナーの様子)

最後に

RPAセミナーに参加して感じた事は、やはりRPAのようなデジタルレイバー(仮想知的労働者)の需要は増加傾向にある、という事です。セミナー会場にいらした方々も、様々な業種の方がいらっしゃいました。 つまり、どの業種にも業務自動化の流れが来ている、という事が分かります。そして同時に、業務自動化に関する正しい知識と認識や、デジタルレイバーの管理方法などを伝授するスキルを持つ人材が必要になると考えられます。 RPAは今後も大きく展開していく可能性があると思います。どのように展開されていくのか、またどのようなスキルが必要になっていくのか、更に注目していこうと思います。

*1:「判断力」や「自己学習能力」によって分けられるクラス

  • Class1:RPA 自己学習能力はなく、定義されたルールに従って処理を行う。
  • Class2:EPA RPAより多くのデータを処理し、分析する機能を有する。AIと同義。
  • Class3:CA  データを分析した上で多様な選択肢を提案する。AIと同義。