【Shell】JDBC を シェルスクリプトでパースする ~ bashによる文字列置換 ~

■ はじめに

PostgreSQL / Redshift の JDBC URL をシェルスクリプトでパースして
各要素を参照する可能性があるので、
以下のサイトを参考にサンプルを実装してみる

https://pslabo.hatenablog.com/entry/20150323/p1

別解:cut / rev コマンドによる方法

cut / rev コマンドによる抽出でも同じことができる
詳細は、以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2021/08/03/160901

目次

【1】bashによる文字列置換
【2】サンプル
【3】補足: JDBC Connection URL Syntax

【1】bashによる文字列置換

パースには、
以下の関連記事で扱った sedコマンドなど
ではない方法「bashによる文字列置換」を使っている

awkコマンド
https://dk521123.hatenablog.com/entry/2019/11/22/223043
sedコマンド
https://dk521123.hatenablog.com/entry/2019/11/23/101625

構文

${変数%マッチパターン}

 * 後方からの検索の一致で一番初めにマッチした部分を削除

${変数%%マッチパターン}

 * 後方からの検索の一致で一番後ろまでマッチした部分までを削除

${変数#マッチパターン}

 * 前方からの検索の一致で一番初めにマッチした部分を削除

${変数##マッチパターン}

 * 前方からの検索の一致で一番後ろまでマッチした部分までを削除

${変数/文字列/処理後文字列}

 * 最初にマッチしたもののみ文字列を置換

${変数//文字列/処理後文字列}

 * 全ての文字列を置換

【2】サンプル

PostgreSQL / Redshift の JDBC URL をシェルスクリプトでパース
# あくまでPostgreSQL / Redshiftのみ。
# 後々調べたら他のDBはフォーマットが違う。。。

parse_jdbc.sh

#!/bin/sh

# [PostgreSQL] (Default Port:5432)
# jdbc:postgresql://[hostname](:[Port])/[DB_name](?properties)
#
# [Redshift] (Default Port:5439)
# jdbc:redshift://[hostname](:[Port])/[DB_name](?properties)
# https://docs.aws.amazon.com/ja_jp/redshift/latest/mgmt/configure-jdbc-connection.html#obtain-jdbc-url

function parse_url_prefix {
  local target=$1
  local url_prefix=${target%%://*}
  echo $url_prefix
}

function parse_protocol {
  local protocol=$( parse_url_prefix $1 )
  local protocol=${protocol%%:*}
  echo $protocol
}

function parse_db_product_type {
  local protocol=$( parse_url_prefix $1 )
  local db_product_type=${protocol#*:}
  echo $db_product_type
}

function parse_host_port_path {
  local target=$1
  local uid_url=${target#*//}
  local uri=${uid_url#*@}
  echo $uri
}

function parse_hostname {
  local uri=$( parse_host_port_path $1 )
  local hostname_port=${uri%%/*}
  local hostname=${hostname_port%%:*}
  echo $hostname
}

function parse_port {
  local uri=$( parse_host_port_path $1 )
  local hostname_port=${uri%%/*}
  local port=${hostname_port#*:}
  local hostname=${hostname_port%%:*}
  if [ "$hostname" == "$port" ]; then
    local db_product_type=$( parse_db_product_type $1 )
    if [ "$db_product_type" == "postgresql" ]; then
      port="5432"
    elif [ "$db_product_type" == "redshift" ]; then
      port="5439"
    else
      # サポート外
      port=""
    fi
  fi
  echo $port
}

function parse_db_name {
  local uri=$( parse_host_port_path $1 )
  local db_name_properties=${uri#*/}
  local db_name=${db_name_properties%%\?*}
  echo $db_name
}

function parse_properties {
  local uri=$( parse_host_port_path $1 )
  local db_name_properties=${uri#*/}
  local db_name=${db_name_properties%%\?*}
  local properties=${db_name_properties#*\?}
  if [ "$db_name" == "$properties" ]; then
    echo ""
  else
    echo $properties
  fi
}

parse_url_prefix $1
parse_protocol $1
parse_db_product_type $1
parse_host_port_path $1
parse_hostname $1
parse_port $1
parse_db_name $1
parse_properties $1

実行結果

$ ./parse_jdbc.sh jdbc:postgresql://localhost:5432/sample_db
jdbc:postgresql
jdbc
postgresql
localhost:5432/sample_db
localhost
5432
sample_db

$ ./parse_jdbc.sh jdbc:postgresql://localhost/sample_db
jdbc:postgresql
jdbc
postgresql
localhost/sample_db
localhost
5432
sample_db


$ ./parse_jdbc.sh jdbc:redshift://127.0.0.1:5439/sample_db
jdbc:redshift
jdbc
redshift
127.0.0.1:5439/sample_db
127.0.0.1
5439
sample_db



$ ./parse_jdbc.sh "jdbc:postgresql://localhost:8080/sample_db?user=symfo&password=secret&ssl=true"
jdbc:postgresql
jdbc
postgresql
localhost:8080/sample_db?user=symfo&password=secret&ssl=true
localhost
8080
sample_db
user=symfo&password=secret&ssl=true

【3】補足: JDBC Connection URL Syntax

protocol//[hosts](:[Port])/database][?properties]

https://docs.oracle.com/cd/E17952_01/connector-j-8.0-en/connector-j-reference-jdbc-url-format.html

PostgreSQL / Redshift 以外のDBに対応したい場合は、
以下のサイトなどでJDBCのURLフォーマットを調べて対応すればいいかと。

https://www.ibm.com/support/knowledgecenter/en/SSEP7J_10.1.1/com.ibm.swg.ba.cognos.vvm_ag_guide.10.1.1.doc/c_ag_samjdcurlform.html
https://docs.oracle.com/cd/E57425_01/121/TDPJD/getconn.htm
https://jdbc.postgresql.org/documentation/head/connect.html
https://docs.oracle.com/cd/E17952_01/connector-j-8.0-en/connector-j-reference-jdbc-url-format.html
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-jdbc-url-format.html

 ぱっと見、以下には、たいおうできてなさげ
 + jdbc:oracle:thin@<HOST>:<PORT>:<DATABASE_NAME>」
 + jdbc:oracle:driver_type:[username/password]@database_specifier

jdbc:postgresql://localhost:5432/sample_db?user=symfo&password=secret&ssl=true

jdbc:redshift://127.0.0.1:5439/sample_db

参考文献

https://pslabo.hatenablog.com/entry/20150323/p1
https://qiita.com/richmikan@github/items/eefbaed716e5ed198973

関連記事

psqlでパスワードを省略する
https://dk521123.hatenablog.com/entry/2020/03/06/000000
awkコマンド
https://dk521123.hatenablog.com/entry/2019/11/22/223043
sedコマンド
https://dk521123.hatenablog.com/entry/2019/11/23/101625
シェル ~ 文字列抽出あれこれ ~
https://dk521123.hatenablog.com/entry/2021/08/03/160901