シェルスクリプトマガジン

test

Bash入門(Vol.83記載)

投稿日:2023.03.25 | カテゴリー: コード

著者:大津 真

LinuxやmacOSなど、UNIX系OSのコマンドラインで使用されるコマンドインタプリタをシェルと呼びます。本連載では高機能シェルとして人気の高い「Bash」の基本操作について説明していきます。最終回となる今回は、シェルで実行可能なプログラミング言語である「シェルスクリプト」について解説します。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図2 図1のコマンド行と同様の処理をするシェルスクリプトの例

# サイズの大きなファイルを見つける
echo "--「~/ピクチャ」以下にある1Mバイト以上のファイル--"
find ~/ピクチャ -type f -size +1M -print0 | \ 
  xargs -0 du | \
  sort -nr | \
  head -n 5

図5 図2のシェルスクリプトを変数を使うように書き換えた例

#!/usr/bin/bash
dir=~/ピクチャ
size="1M"
echo "--「${dir}」以下にある${size}バイト以上のファイル--"
find "$dir" -type f -size "+${size}" -print0 | \
  xargs -0 du | \
  sort -nr | \
  head -n 5

図6 図5のシェルスクリプトをコマンドライン引数を参照するように書き換えた例

#!/usr/bin/bash
dir=$1
size="1M"
echo "--「${dir}」以下にある${size}バイト以上のファイル--"
find "$dir" -type f -size "+${size}" -print0 | \
  xargs -0 du | \
  sort -nr | \
  head -n 5

図7 if文を使用したシェルスクリプトの例

#!/usr/bin/bash
if cd $1 2>/dev/null
then
  echo "${1}に移動しました"
else
  echo "${1}に移動できませんでした"
fi

図8 図6のシェルスクリプトを条件式とif文を使って書き換えた例

#!/usr/bin/bash
if [ $# -eq 0 ]
then
  echo "エラー: 引数でディレクトリを指定してください"
  exit 1 ←③
fi
if [ ! -d "$dir" ]
then
  echo "エラー: ${dir}が見つかりません"
  exit 1
fi
size="1M"
echo "--「${dir}」以下にある${size}バイト以上のファイル--"
find "$dir" -type f -size "+${size}" -print0 | \
  xargs -0 du | \
  sort -nr | \
  head -n 5

図9 for文を使ったシェルスクリプトの例

#!/usr/bin/bash
four_seasons="春 夏 秋 冬"
for season in $four_seasons
do
    echo "$season"
done

図10 図8のシェルスクリプトをfor文を使って書き換えた例

#!/usr/bin/bash
if [ $# -eq 0 ]
then
  echo “エラー: 引数でディレクトリを指定してください”
  exit 1
fi
size="1M"
for dir in "$@"
do
  if [ ! -d “$dir” ]
  then
    echo "エラー: ${dir}が見つかりません"
  else
    echo "--「${dir}」以下にある${size}バイト以上のファイル--"
    find $dir -type f -size "+${size}" -print0 | \
      xargs -0 du | \
      sort -nr | \
      head -n 5
  fi
done

図12 配列を使ったシェルスクリプトの例

#!/usr/bin/bash
if [ $# -eq 0 ] || [ ! -d $1 ]
then
  echo "エラー: 引数でディレクトリを指定してください"
  exit 1
fi
target=~/公開/pictures
extensions=(jpg jpeg png gif pdf)
for ext in "${extensions[@]}"
do
  for file in "$1"/*.${ext}
  do
    if [ -f "$file" ]
    then
      cp -v "$file" $target
    fi
  done
done

香川大学SLPからお届け!(Vol.83掲載)

投稿日:2023.03.25 | カテゴリー: コード

著者:安田 大朗

最近、さまざまな場面でチャットbotなどの対話システムを見かけます。その中には、感情表現の機能を持ち、より人間らしい振る舞いをするものもあります。私はそうした対話システムに興味があり、ユーザーが入力したテキストの感情を分析し、それに応じた反応をする対話システムを作成しました。今回は、私が開発したその対話システムについて紹介します。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図4 「telegram-bot.py」ファイルに記述するコード

from telegram.ext import (Updater, CommandHandler,
                          MessageHandler, Filters)

TOKEN = "トークン"
class TelegramBot:
  def __init__(self, system):
    self.system = system
  def start(self, update, bot):
    input = {'utt':None, 'sessionId':str(update.message.from_user.id)}
    update.message.reply_text(self.system.initial_message(input)["utt"])
  def message(self, update, bot):
    input = {'utt':update.message.text,
             'sessionId':str(update.message.from_user.id)}
    system_output = self.system.reply(input)
    update.message.reply_text(system_output["utt"])
  def run(self):
    updater = Updater(TOKEN, use_context=True)
    dp = updater.dispatcher
    dp.add_handler(CommandHandler("start", self.start))
    dp.add_handler(MessageHandler(Filters.text, self.message))
    updater.start_polling()
    updater.idle()

図5 「aim_system1.py」ファイルに記述するコード

import aiml
import MeCab
from telegram_bot import TelegramBot

class AimlSystem:
  def __init__(self):
    self.sessiondic = {}
    self.tagger = MeCab.Tagger('-Owakati')
  def initial_message(self, input):
    sessionId = input['sessionId']
    kernel = aiml.Kernel()
    kernel.learn("aiml.xml")
    self.sessiondic[sessionId] = kernel
    return {'utt':'はじめまして,雑談を始めましょう',
            'end':False}
  def reply(self, input):
    sessionId = input['sessionId']
    utt = input['utt']
    utt = self.tagger.parse(utt)
    response = self.sessiondic[sessionId].respond(utt)
    return {'utt':response, 'end':False}

if __name__ == '__main__':
    system = AimlSystem()
    bot = TelegramBot(system)
    bot.run()

図6 「aim.xml」ファイルに記述するルールの例

<?xml version="1.0" encoding="UTF-8"?>
<aiml version="1.0.1" encoding="UTF-8">
 <category>
    <pattern>* へ 旅行 に 行き まし た</pattern>
    <template><star/>に旅行ですか,いいなー.</template>
  </category>
  <category>
    <pattern>私 の 名前 は * です</pattern>
    <template><set name="username"><star/></set>さん、よろしくね!.</template>
   </category>
  <category>
    <pattern>じゃあね</pattern>
    <template><get name="username"/>さん、バイバイー.</template>
  </category>
</aiml>

図8 「aim_system2.py」ファイルに記述するコード

    response = self.sessiondic[sessionId].respond(utt)
    emotion_dic = {'suki':'🥰', 'ikari':'😡', 'kowa':'😱',
                   'yasu':'😊', 'iya':'😫', 'aware':'😭',
                   'takaburi':'🤩', 'odoroki':'🙄', 'haji':'🤭',
                   'yorokobi':'😄'}
    emotion_analyzer = MLAsk()
    json_emot = emotion_analyzer.analyze(utt)
    if json_emot['emotion'] == None:
      return {'utt':response, 'end':False}
    else:
      emotion = json_emot['representative'][0]
      return {'utt':response + emotion_dic[emotion], 'end':False}

if __name__ == '__main__':

Pythonあれこれ(Vol.83掲載)

投稿日:2023.03.25 | カテゴリー: コード

著者:飯尾 淳

本連載では「Pythonを昔から使っているものの、それほど使いこなしてはいない」という筆者が、いろいろな日常業務をPythonで処理することで、立派な「蛇使い」に育つことを目指します。その過程を温
かく見守ってください。皆さんと共に勉強していきましょう。第13回では、PyTorchという機械学習ライブラリを使って、手書きの数字を画像認識によって分類してみます。実際に作業することで、機械学習の効果を感じてください。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図1 MNISTデータセットをダウンロードするためのコード

data_folder = '~/data'
BATCH_SIZE = 8
mnist_data = MNIST(data_folder, 
                   train=True, 
                   download=True, 
                   transform=transforms.ToTensor())
data_loader = DataLoader(mnist_data, 
                         batch_size=BATCH_SIZE, 
                         shuffle=False)

図4 MNISTデータセットのデータを1セット表示するコード

data_iterator = iter(data_loader)
images, labels = next(data_iterator)
# 最初の画像を表示
location = 0
# 画像データを28×28画素のデータに変換して表示
data = images[location].numpy()
reshaped_data = data.reshape(28, 28)
plt.imshow(reshaped_data, cmap='inferno', interpolation='bicubic')
plt.show()
print('ラベル:', labels[location])

図6 学習データと検証データを用意するコード

# 学習データ
train_data_loader = DataLoader(
    MNIST(data_folder, train=True, download=True, 
          transform=transforms.ToTensor()),
    batch_size=BATCH_SIZE, shuffle=True)
# 検証データ
test_data_loader = DataLoader(
    MNIST(data_folder, train=False, download=True, 
          transform=transforms.ToTensor()),
    batch_size=BATCH_SIZE, shuffle=True)

図9 ニューラルネットワークモデルを定義するコード

from torch.autograd import Variable
import torch.nn as nn
# 親クラスのnn.Moduleを継承してモデルを作成
class MLP(nn.Module):
  def __init__(self):
    super().__init__()
    self.layer1 = nn.Linear(28 * 28, 100)
    self.layer2 = nn.Linear(100, 50)
    self.layer3 = nn.Linear(50, 10)
  def forward(self, input_data):
    input_data = input_data.view(-1, 28 * 28)
    input_data = self.layer1(input_data)
    input_data = self.layer2(input_data)
    input_data = self.layer3(input_data)
    return input_data

図11 学習前の準備をするコード

import torch.optim as optimizer

# モデルの作成
model = MLP()
# 評価器(誤差項)と最適化器の作成
lossResult = nn.CrossEntropyLoss()
optimizer = optimizer.SGD(model.parameters(), lr=0.01)

図12 画像認識の精度を検証するコード

import torch

# 検証した数と正解の数
total = 0
count_when_correct = 0
for data in test_data_loader:
  test_data, teacher_labels = data
  results = model(Variable(test_data))
  _, predicted = torch.max(results.data, 1)
  total += teacher_labels.size(0)
  count_when_correct += (predicted == teacher_labels).sum()
rate = int(count_when_correct) / int(total)
print(f'count_when_correct:{count_when_correct}')
print(f'total:{total}')
print(f'正解率:{count_when_correct} / {total} = {rate}')

図13 モデルを学習させるコード

# 最大学習回数
MAX_EPOCH = 4
for epoch in range(MAX_EPOCH):
  total_loss = 0.0
  for i, data in enumerate(train_data_loader):
    train_data, teacher_labels = data
    train_data, teacher_labels = \
      Variable(train_data), Variable(teacher_labels)
    # 勾配情報をリセット
    optimizer.zero_grad()
    outputs = model(train_data)
    loss = lossResult(outputs, teacher_labels)
    loss.backward()
    # 勾配を更新
    optimizer.step()
    # 誤差を積み上げる
    total_loss += loss.data
    if i % 2000 == 1999:
      print(f'学習進捗:[{epoch+1}, {i+1}]', end='')
      print(f'学習誤差(loss): {total_loss / 2000:.3f}')
      total_loss = 0.0
print('学習終了')

図15 個別の判定結果を確認するコード

# データの取得と検証
test_iterator = iter(test_data_loader)
test_data, teacher_labels = next(test_iterator)
results = model(Variable(test_data))
_, predicted_label = torch.max(results.data, 1)
# 最初のデータを検証して画像を表示
location = 0
plt.imshow(test_data[location].numpy().reshape(28, 28), 
           cmap='inferno', interpolation='bicubic')
print('ラベル:', predicted_label[location])

特別企画 Raspberry Piを100%活用しよう 拡大版(Vol.83記載)

投稿日:2023.03.25 | カテゴリー: コード

著者:米田 聡

小型コンピュータボード「Raspberry Pi」(ラズパイ)向けにさまざまな拡張ボードが発売されています。その拡張ボードとラズパイを組み合わせれば、ラズパイでいろいろなことが簡単に試せます。本企画では、ラズパイと連携して使用するマイコンボードを扱います。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図A uf2conv.pyの修正箇所

(略)
    return resfile

def to_str(b):
#    return b.decode("utf-8")
    return b.decode("cp932")

def get_drives():
    drives = []
(略)

特集1 Ruby on Rails入門(Vol.83記載)

投稿日:2023.03.25 | カテゴリー: コード

著者:安川要平

本特集では、地図アプリの作成を題材に、Webアプリケーションフレームワーク「Ruby on Rails」によるWebアプリの開発手順を紹介します。説明は、米GitHub社が提供するクラウド開発環境「GitHub Codespaces」を使って進めます。そのため、Webブラウザさえあれば紹介する手順を確認できます。Webブラウザだけで体験できるようになった最新のRubyとRailsを一緒に触ってみましょう。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図15 「app/models/spot.rb」ファイルに追加する1行

class Spot < ApplicationRecord
  has_one_attached :photo
end

図16 「app/views/apots/_form.html.erb」ファイルに追加する記述

(略)
  <div>
    <%= form.label :name, style: "display: block" %>
    <%= form.text_field :name, readonly: false %>
  </div>
  <div>
    <%= form.label :photo, style: "display: block" %>
    <%= form.file_field :photo, readonly: false %>
  </div>
  <div>
    <%= form.submit %>
  </div>
<% end %>
(略)

図18 「app/controllers/spots_controller.rb」ファイルに追加する記述

(略)
    # Only allow a list of trusted parameters through.
    def spot_params
      params.require(:spot).permit(:lat, :lng, :name, :photo)
    end

end

図19 「app/helpers/spots_helper.rb」ファイルに追加する記述

(略)
    html << "<strong>Name:</strong> #{spot.name}<br />"
    if spot.photo.attached?
      html << "<strong>Photo:</strong> #{image_tag(spot.photo, width: '100%')}<br />"
    end
    return html.html_safe
  end
end

図25 提供されるサンプルデータの内容

[
  {
    id:    "1037",
    lat:   "35.7087568",
    lng:   "139.7196777",
    name:  "早大で入試「一般選抜」がスタート"
    photo: "https://localmap.jp/images/takadanobaba/1037.jpg",
    url:   "https://takadanobaba.keizai.biz/headline/1037/",
  },
(略)
]

図26 サンプルデータを取得して画面に表示するコード

require 'net/http' # 'net-http'ではないことに注意
uri = URI('https://localmap.jp/scaffold.json')
response = Net::HTTP.get(uri)   # ファイルを取得 
map_data = JSON.parse(response)	# 結果を変数に格納
p map_data # 画面に表示	

図28 サンプルデータを自動入力するコード

require 'net/http'
uri = URI('https://localmap.jp/scaffold.json')
response = Net::HTTP.get(uri)
map_data = JSON.parse(response)

# 各スポットのデータ(map)に対して以下のコードを実行
map_data.each do |map|
  # 新規スポットにサンプルデータを入力
  spot = Spot.new(
    lat:  map['lat'],
    lng:  map['lng'],
    name: map['name'],
  )
  # 新規スポットに画像を添付
  spot.photo.attach(
    io: URI.open(map['photo']),
    filename: map['id'] + '.jpg',
  )
  # 新規スポットをDBに保存
  spot.save
end

レポート2(Vol.83掲載)

投稿日:2023.03.25 | カテゴリー: コード

著者:末安 泰三

話題のAIチャットボット「ChatGPT」のAP(I Application Programming Interface)を、開発元の米OpenAIが有償公開した。APIの公開により、自作プロダクトにChatGPTの機能を手軽に組み込めるようになった。2023年3月時点の利用料金は、1000トークン当たり0.002ドルだ。

シェルスクリプトマガジン Vol.83は以下のリンク先でご購入できます。

図1 ChatGPT APIを利用するPythonコードの例

import openai
openai.api_key = "ここにAPIキーを記述する"
response = openai.ChatCompletion.create(
  model = "gpt-3.5-turbo",
  messages = [
    {"role":"system", "content":"①ChatGPTの動作をここで指定する"},
    {"role":"user", "content":"②ChatGPTに送るメッセージを記述する"}
  ]
)
print(response['choices'][0]['message']['content'])

シェルスクリプトマガジンvol.83 Web掲載記事まとめ

投稿日:2023.03.25 | カテゴリー: コード

004 レポート モーションキャプチャ「mocopi」 サンプル動画掲載
005 レポート ChatGPT API公開 コード掲載
006 製品レビュー ウエアラブルデバイス「Redmi Smart Band2」
007 NEWS FLASH
008 特集1 Ruby on Rails入門/安川要平 コード掲載
020 特集2 AutoML徹底解説 入門編/田村孝、山口武彦、新田陸、細野友基
034 特別企画 Raspberry Piを100%活用しよう 拡大版/米田聡 コード掲載
044 Pythonあれこれ/飯尾淳 コード掲載
049 Hello Nogyo!
050 香川大学SLPからお届け!/安田大朗 コード掲載
056 法林浩之のFIGHTING TALKS/法林浩之
058 中小企業手作りIT化奮戦記/菅雄一
062 SCM/桑原滝弥、イケヤシロウ
064 タイ語から分かる現地生活/つじみき
070 行動経済学と心理学で円滑に業務を遂行/請園正敏
074 AWKでデジタル信号処理/斉藤博文
082 ユニケージ通信/田渕智也、高橋未来哉
086 Bash入門/大津真 コード掲載
096 Techパズル/gori.sh
097 コラム「ユニケージ式プロジェクト管理法」/シェル魔人

Vol.83

投稿日:2023.03.25 | カテゴリー: バックナンバー

 過去に爆発的な人気を博した、プログラミング言語「Ruby」のWebアプリケーションフレームワーク「Ruby on Rails」ですが、現在では「死んだ」と言われています。しかし、昨年11月にRuby on Railsのドキュメントや教育、マーケティングなどを支援する団体「Rails財団」が設立されました。また、昨年末にRubyの新版「Ruby 3.2」がリリースされました。このようにRuby on RailsおよびRubyに対して大きな変化が訪れています。
 特集1では、地図アプリの作成を題材に、Ruby on RailsによるWebアプリケーション開発を紹介します。素早くプログラミングができるRuby on Railsを体験してみてください。
 特集2では、入門編として、AI(人工知能)の機械学習において最近話題の「AutoML」(Automated Machine Learning)を解説します。AutoMLは、機械学習モデルに係る作業を完全に自動化し、機械学習の知識がなくても簡単にAIの実装を可能にする技術です。データサイエンティストなどの専門家でなくてもAIが扱えますので、ぜひ注目してください。
 特別企画では、2023年3月10日にビット・トレード・ワンから発売された拡張ボード「ラズベリーパイ接続 RP2040エッジアクセラレータ」の使い方を2回に分けて紹介します。同ボードは、Raspberry Pi Picoに搭載されているArmプロセッサ「RP2040」を備えていて、Raspberry Pi Pico以外のRaspberry Piと連携して利用します。リアルタイム制御など、Raspberry Pi Pico以外のRaspberry Piのみでは実現できないことも可能です。
 このほか、連載「香川大学SLPからお届け!」では、メッセージの感情表現を絵文字で表すチャットボットの作成方法を、連載「中小企業手作りIT化奮戦記」では、新システム導入時に発生した数々の問題を紹介しています。どちらも大変面白い内容になっています。
 今回も読み応え十分のシェルスクリプトマガジン Vol.83。お見逃しなく!

※記事掲載のコードはこちら。記事の補足情報はこちら

※読者アンケートはこちら

Vol.83 補足情報

投稿日:2023.03.25 | カテゴリー: コード

特別企画 Raspberry Piを100%活用しよう 拡大版

 同企画で扱いました、PlatformIO向けのRP2040用ソフトウエア基盤(フレームワーク)が「https://github.com/Wiz-IO/wizio-pico」から入手できなくなってしまいました。原作者に問い合わせましたが、返答はなく理由は不明です。ご迷惑をおかけして申し訳ございません。
 「https://github.com/Wiz-IO/wizio-pico」にアクセスして図1のように表示されたときは、以下の方法で入手・導入してください。
(1)特別企画記事の通りに開発ツール「Visual Studio Code」(VSCode)とWindows版Gitクライアント「Git for Windows」をインストールします。
(2)PlatformIO向けのRP2040用ソフトウエア基盤(フレームワーク)を「https://future.quake4.jp/wizio-pico.zip」からダウンロードします。
(3)VSCodeを起動しているならいったん終了します。
(4)「C:¥Users¥ユーザー名¥.platformio¥」(ユーザー名はWindowsのアカウント名)の下にダウンロードした「wizio-pico.zip」ファイルを展開します。

図1 ページが見つからない場合の表示

情報は随時更新致します。

  • shell-mag ブログの 2023年3月 のアーカイブを表示しています。

  • -->