Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[Bash] ヒアドキュメントを利用してbashからpythonの力を借りる

はじめに

shellでファイルをパースするのは結構しんどい。
正規表現を使って頑張って書いてもいいが、たいていは時間が経つと内容を忘れてしまう。
pythonのモジュールの力を借りることで正規表現の苦労から抜け出せたケースがあった。
これはその時の記録。

環境

  • OS
    • CentOS 7.4
  • bash
    • GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
  • Python
    • Python 3.6.8

具体的にはどうすればよいのか

bashのヒアドキュメントを利用してpythonコマンドに対してpythonのコードを流し込む。

shellscript
python <<EOF

# pythonのコード

EOF

尚bashのヒアドキュメントについてはここでは書きません。
詳しく知りたい方はご自身でお調べください。

サンプル

以下はサンプル。
pythonのconfigparserモジュール使ってmysql用のconfファイルを解析してMySQLに接続するshell scriptになっています。

connect_mysql.sh
#!/usr/bin/env bash
#
# Connect to MySQL

declare -r COLOR_RED="\e[33;41;1m"
declare -r COLOR_OFF="\e[m"
declare -r DB_CONFIG_PATH='path/to/database.conf'
# check file exists or not
if [ ! -f "${DB_CONFIG_PATH}" ]; then
  echo -e "${COLOR_RED}[error] \"${DB_CONFIG_PATH}\" does not exist.${COLOR_OFF}"
  exit 1
fi

declare -r SECTION=$1
# check argument
if [ -z "$SECTION" ]; then
  echo -e "${COLOR_RED}[error] Please set section name as command argument.${COLOR_OFF}"
  exit 1
fi


#######################################
# Parse DB config by python
# Globals:
#   DB_CONFIG_PATH
#   SECTION
# Arguments:
#   None
# Returns:
#   None
#######################################
function parse_ini_file () {

  python3 <<'EOF' - "${DB_CONFIG_PATH}" "${SECTION}"

import sys
import configparser

file_path    = sys.argv[1]
section_name = sys.argv[2]

config = configparser.ConfigParser()

config.read(file_path)

try:
    details = config[section_name]
except KeyError:
    sys.exit(1)

db_option = \
    '[client]\\nhost={host}\\nport={port}\\ndatabase={database}\\nuser={user}\\npassword={password}\\n'\
    .format(\
        host=details['host'],\
        port=details['port'],\
        database=details['database'],\
        user=details['user'],\
        password=details['password']\
    )

sys.stdout.write(db_option)
sys.exit(0)

EOF


}

db_option=$(parse_ini_file)

if [ $? -ne 0 ]; then
  echo -e "${COLOR_RED}[error] Section \"${SECTION}\" does not exist in config file.${COLOR_OFF}"
  exit 1
fi

mysql --defaults-extra-file=<(echo -e ${db_option})

下記の様にすればヒアドキュメントでもpython ファイル名 引数1 引数2のようなことができるらしい。

python3 <<'EOF' - "${DB_CONFIG_PATH}" "${SECTION}"
...
EOF

おわりに

どなたかのお役に立てば幸いです。

r_sui
2008年に中小企業のソフトハウスに入社して技術者としてのキャリアをスタート。会社員(08年10月-17年12月)→フリーランス(18年1月-20年3月)→会社員(20年4月-)という経歴。現在はPHPで作られたWEBシステムの開発・運用をしています。経験が長い言語はPHP、javascript、Bash。テキストエディタはVim派。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away