OmniAICreator/Qiita-1.07M huggingface dataset:
【文字数カウント】指定フォルダ内に存在するテキストファイルを一括で計算

業務上、テキストファイルの文字数を計算することが多くありました。

「フォルダ丸ごと文字数カウント」
できるソフトが見つからなかったため、作成しました。

◆言語
VB.Net

◆実行ボタン押下前
![mojicount_mae.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585109/1936f78c-7ffd-93bc-225f-79757872aefd.jpeg)

◆実行ボタン押下後
![mojicount_ato.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/585109/37aa3f4c-4c6c-61dd-53e4-0a1a0426d0a7.jpeg)


◆ソースコード

Imports System.IO
Imports System.Windows.Forms
Imports System.Text


Public Class FrmMain



    ''' <summary>
    ''' メイン処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnExe_Click(sender As Object, e As EventArgs) Handles btnExe.Click

        Try

            '文字数をクリア
            lblTotal.Text = String.Empty

            '入力チェック
            If InputCheck() = False Then
                MessageBox.Show("入力値が正しくありません。")
                Exit Sub
            End If

            '読み込み処理
            ReadProcess()

        Catch ex As Exception
            MessageBox.Show("エラーです。" & vbCrLf & ex.ToString)
        End Try
    End Sub

    ''' <summary>
    ''' 入力チェック
    ''' </summary>
    ''' <returns></returns>
    Private Function InputCheck() As Boolean
        If String.IsNullOrEmpty(tbxRead.Text.Trim) OrElse Directory.Exists(tbxRead.Text.Trim) = False Then
            Return False
        End If
        Return True
    End Function

    ''' <summary>
    ''' 読み込み処理
    ''' </summary>
    Private Sub ReadProcess()

        Dim di As New System.IO.DirectoryInfo(tbxRead.Text)
        Dim files As System.IO.FileInfo() =
            di.GetFiles("*.txt", System.IO.SearchOption.AllDirectories)

        Dim txtPathList As List(Of String) = New List(Of String)
        For Each f As System.IO.FileInfo In files
            txtPathList.Add(f.FullName.ToString)
        Next

        If txtPathList.Count = 0 Then
            MessageBox.Show("テキストファイルが存在しませんでした。")
            Return
        End If

        Dim total As Integer
        For idx As Integer = 0 To txtPathList.Count - 1

            'テキストファイルを開く
            Dim bs As Byte() = System.IO.File.ReadAllBytes(txtPathList(idx))
            Dim sr As New StreamReader(txtPathList(idx).ToString, Encoding.Default)
            Dim str As String = sr.ReadToEnd()
            sr.Close()
            total += str.Length
        Next

        lblTotal.Text = "合計" & total & "文字"

    End Sub

    ''' <summary>
    ''' フォルダ選択ボタンの押下
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub btnOfd_Click(sender As Object, e As EventArgs) Handles btnFdb.Click

        Dim fbd As New FolderBrowserDialog

        fbd.Description = "フォルダを指定してください。"
        fbd.RootFolder = Environment.SpecialFolder.Desktop
        fbd.SelectedPath = "C:\Windows"
        fbd.ShowNewFolderButton = True

        If fbd.ShowDialog(Me) = DialogResult.OK Then
            tbxRead.Text = fbd.SelectedPath
        End If

    End Sub
End Class
S3バケットを空にするRubyスクリプト

APIなどでバケットを削除する際、空にしてからでないと削除できません。バケットを空にするプログラムを作るのは、けっこうな手間なのですが、Rubyだと一発でいけます。

```ruby:clear-bucket.rb
require 'aws-sdk-s3'
bucket = Aws::S3::Bucket.new('<バケット名>')
bucket.clear!
```
dockerの課題

docker 利用を進めてきて現在の作業上の課題または課題の候補を記録する。


#  32bit CPUで、古いWindowsで動作しない

docker for windowsがうなく導入または起動できていない。
直接まだ確かめていない。

# PC用OS(windows, macOS, linux)側のdockerの版管理

どのOSのどの版ではdockerのどの版が安定して動作するか。

# dockerのcomponent管理

古いcomponentでないと動作しない場合があるかどうか。
直接まだ確かめていない。

# X windowsとの連携

Eclipse cheなどX Windowsを利用するソフトウェアなどの、Windows, mac OSでの動作のさせ方

# docker hubに登録したソフトの管理

apt update, apt -y upgrade
をしてもよいか、しない方がよいかなどの指針。

# security対策

どの水準で、どういうsecurity対策をするとよいか。


#参考資料(reference)

Eclipse che
https://qiita.com/kaizen_nagoya/items/cb8b68694ee5355789c6
【ふくだ学習録】アプリ制作part5【32日目】

# ふくだ学習録とは？
ふくだが学習したことの備忘録。
目に見える形で残すことによってやる気を出す個人的な作戦です。
他人に見せるように書いているわけではないので、すごく読みにくいです。

### 読了した本
[データベースエンジニア養成読本 [DBを自由自在に活用するための知識とノウハウ満載!]](https://www.amazon.co.jp/dp/4774158062/ref=cm_sw_r_tw_dp_U_x_FPphEbQFPPQRM )
[ゼロから作るDeepLearning](https://www.amazon.co.jp/dp/4873117585/ref=cm_sw_r_tw_dp_U_x_y3UiEbF3P6EG7)
[PHPフレームワーク CakePHP 3入門](https://www.amazon.co.jp/dp/4798048577/ref=cm_sw_r_tw_dp_U_x_.YIjEbS1K4JY2)
[SQLアンチパターン](https://www.amazon.co.jp/dp/4873115892/ref=cm_sw_r_tw_dp_U_x_XlokEbJQK2N7P )
[Docker入門](https://www.amazon.co.jp/dp/480071091X/ref=cm_sw_r_tw_dp_U_x_xVlmEbN8ZTHZK)


### 今読んでいる本

なし

# アプリ制作

### テーブル設計
今日からはRDB設計。アプリでいうとここ。
<img width="703" alt="スクリーンショット 2020-02-13 9.01.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356866/e182ad0d-09de-70e1-d8da-9ab0eb8af8c6.png">

スクレイピング部分の作成とテーブル設計、どっちを先にするか迷ったけど、テーブル設計することにしました。

最初は
**①（スクレイピングで）どんな情報を取得できるかどうか確認**
**②（取得できた情報を）どういう風に情報格納するのか決めてテーブル設計**
って流れでいこうと思ったけど、それって結局行き当たりばったりやし、手段と目的が逆転しちゃうイメージなので辞めました。

本来は
**①サービス実現のためにはどんな情報が必要か**
**②サービスをアプリケーションに落とし込むためには、情報をどういう形で整理格納しておくべきか**
**③アプリケーションを実現するための情報をどういう風に取得していけばいいか**
こういった順序で考えていくべきだなと。

スクレイピングはあくまで③部分なので、先に③から始めちゃうと本来優先すべき①②が考えれなくなっちゃう（諦めちゃう）なと思い、先にテーブル設計していくことにします。③の主な手段はスクレイピングで実現するけど、それが無理な場合は別手段考える！

### データベース設計（テーブル設計）の際に参考にしたもの
命名規則関連は下記記事参考に進めています。
[データベースオブジェクトの命名規約](https://qiita.com/genzouw/items/35022fa96c120e67c637)

あとは参考に[4ステップで作成する、DB論理設計の手順とチェックポイントまとめ](https://qiita.com/nishina555/items/a79ece1b54faf7240fac)も見た。

### ふくだ流テーブル設計の考え方、進め方

実際に今設計中ですが、主にこんな考え方で進めてます。（あんまり効率よくないよ！とかあれば言っていただきたい！）

**①一番重要なエンティティを考える。（以後主エンティティと呼ぶ）**

**②主エンティティはどのようなデータ（属性）を保持しているかを考える。それらをフィールドにし主エンティティテーブルを作成する。**

**③主エンティティテーブル内のフィールドの中でも「格納されるデータにパターン性がある」かつ「格納されるデータ自体が、それだけで完結しない（オブジェクトとして他データを保持して欲しい）」フィールドは、別エンティティとして切り分けられるので、別テーブルとして作成する。**

**④主エンティティテーブルと、切り分けられたエンティティで作られたテーブルには何かしたのリレーションがあるので、リレーションテーブルを作成する。**

って流れで作っています。（思考の言語化結構大変）

自己流なので、これが一般的なのかすごいダメなやり方なのかはわからないですが、プログラミングでいうリファクタリング的な感じで結構サクサク進めれるので、まぁまぁいいやり方なんじゃないかなと思ってる。

# 今日の一言
今日はちょいとTypeScriptいじって、テーブル設計したー。
Typescript×VScodeがすごい開発の手助けしてくれるってのを肌で実感した！ありがてぇ。
テーブル設計は自己流なので、あんまりいいやり方じゃないかもやけど、個人的には進めやすいので初期設計はこのやり方で進める！
reCAPTCHAのサイトを毎日自動スクレイピングする (3/7: xlsファイル処理)


1. [要件定義〜python環境構築](https://qiita.com/kamyu1201@github/items/65a86ec1e28ec9969dcb)
1. [サイトのスクレイピング機構を作る](https://qiita.com/kamyu1201@github/items/a07c7d175c051b8ab4c0)
1. **ダウンロードしたファイル(xls)を加工し、最終成果物(csv)を作成するようにする**
1. S3からのファイルダウンロード / S3へのファイルアップロードをつくる
1. 2captchaを実装
1. Dockerコンテナで起動できるようにする
1. AWS batchに登録


# ファイル操作

前回まででseleniumを使ったファイルダウンロードを行ったので、
それを取得・加工してcsvファイルとして保存し直す処理を記載します。



### ファイル一覧を取得
特定のフォルダ内の特定パターンのファイルをすべて取得する！
というときはglobが便利。

```python
# 当該正規表現のファイルリストを取得(glob)
file_list = glob.glob(dl_dir+'/*')
```

### Excelファイルの操作
pythonによるexcel操作はいくつかライブラリがあるようですが、ひとつ覚えておくと便利そう。私はxlrdを使います。

```python
# Excelファイルの操作
wb = xlrd.open_workbook(file_name) #xlsを開く
sheet_names = wb.sheet_names() #シート名一覧を取得
sheet = wb.sheet_by_name(sheet_names[1]) 
values2 = sheet.col_values(2)
values5 = sheet.col_values(5)
values2.pop(0) #1行目をなくすため…。もっといいやり方あるのかな
values5.pop(0)
for i in range(len(channels)):
    obj = [
        word,
        someFunction2(values2[i]),
        someFunction5(values5[i])
    ]
    result.append(obj)
```

### csvファイルに保存
```python
with open(up_dir + '/result-{}.csv'.format(file_name), 'w') as f:
    writer = csv.writer(f)
    writer.writerows(result)
```

## 完成
ここまでで、

- 実行するとサイトをスクレイピングしてファイルをダウンロードし
- それを加工したものを特定フォルダに置く

というところまでできました。
次は、「加工したものをS3に送る」ところと、「そもそものINPUT(words)をS3から取得する」ところを書いていきます。
AUTOSARの利点と方向性, OSEK(50)

AUTOSAR
http://autosar.org

2002年に協議が始まった頃は、ISO OSEK、ISO CANなどの国際規格に基づいた自動車のソフトウェアの基本的な土台を体系化して設計の道具類を整備することを目的としていると認識していた。
https://www.autosar.org/about/history/

この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# Specification
OSと通信などの関係が、それぞれ別の規格だと、なかなか統一的に理解するのは難しい。

自動車以外の分野で、UNIX系でもOSを規定するPOSIXとネットワークを定義するIETF RFCとの間を容易に統合的に理解できるとは限らない。

Adaptive Platformで、POSIX, IETF RFCを取り込もうとしているのは興味深い。
# Requirement
当初の文書では、どのRequirementをどの組織が提出したかを記録していた。

自動車製造業、部品製造業、半導体製造業など、関係者の興味がどこにあり、どこに潜在的な必要性があるかを推測できた。

# International standard
OS, 通信の国際規格との連携がより明確になった。

LINは長らく国際規格になっていなかったが、2016年に国際規格になった。

AUTOSAR related Standard
https://qiita.com/kaizen_nagoya/items/13b163f8515615ecc648

LIN
https://www.iso.org/standard/61222.html

## Diagnostic
Diagnositicは各社の仕様が異なっていた。
通信面など共通にできる部分の国際規格化が進んでいる。

ISO Road vehicles Diagnostics 規格調査中　100規格、100記事をめざして。
https://qiita.com/kaizen_nagoya/items/51e29d318585a4219985

ISO Road vehicles Diagnostics 規格調査中　100規格、100記事の方針
https://qiita.com/kaizen_nagoya/items/da41dbb1965ac4be0172
# Test
試験についての枠組みも順次規定している。

# Tool
道具類の枠組みの一部は規定しているが、方向性をまだ理解できていない。

# Application

## CASE
Connected（コネクティッド）、Autonomous/Automated（自動化）、Shared（シェアリング）、Electric（電動化）
https://global.toyota/jp/mobility/case/

# 方向性
電池制御、充電など電動化の土台となる仕組みを、外部の規定を引用するとよいかもしれない。
乗っ取り防止などの通信の防御の仕組みを、外部の規定を引用するとよいかもしれない。
自動運転の低速安全状態と、高速安全状態の両方に共通な土台として何が重要かなどの規定を、外部の規定を引用するとよいかもしれない。
Automotive Grade Linux（AGL）
https://qiita.com/kaizen_nagoya/items/36ee958a765833e26c29
のような関連規格・企画が連携して、牽引していくとよい。
AI／DL／量子計算機とのI/Fが成熟していくとよい。

# Refeernce
物理記事　上位100
https://qiita.com/kaizen_nagoya/items/66e90fe31fbe3facc6ff

数学関連記事１００
https://qiita.com/kaizen_nagoya/items/d8dadb49a6397e854c6d

言語・文学記事　１００
https://qiita.com/kaizen_nagoya/items/42d58d5ef7fb53c407d6

医工連携関連記事一覧
https://qiita.com/kaizen_nagoya/items/6ab51c12ba51bc260a82

通信記事１００
https://qiita.com/kaizen_nagoya/items/1d67de5e1cd207b05ef7

自動車　記事　１００
https://qiita.com/kaizen_nagoya/items/f7f0b9ab36569ad409c5

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.

### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
VIMは使えるに越したことない—最低限そつなく使うためのとっかかり

VIMは主にLINUX環境下で使われるテキストエディタです。
非常に癖があって、未経験の人にとっては異世界の産物のように見えますが、ある程度使って行けば自転車の乗り方を覚えるようにスムーズに操作できるようになります。

VIMのいいところは

・読み書きが非常に速い（通常、膨大な量のJSONなどを読み書きすると処理落ちする）
・キータッチする範囲がせまいため、指への負担が少ない
・.vimrcを書き換えるだけである程度素敵なカスタムが出来る（来夢のカスタマイズはウィジェットが関わることがあって面倒だしものによっては重くなる）

ということがあげられます。

最近はVSCodeなどに移っていってVIMから離れる人、最初からVIMを使わない人も結構いるようですが、コーディングをしないにせよ、Linux内のファイルを開いたり編集したりすることを考えると覚えておくに越したことはありません。

以下、VIMなんて経験ないよと言う人が、まず「使ってみたいな」という人のためのイントロ的な部分について説明します。
これだけ覚えておけば、コーディングではないちょっとした文章加工程度なら苦労なくできるようになります。

 
#０．全機能をいきなり使いこなすのは無理
VIMにはいろいろな機能があり、現時点で使い始めて1年足らずの筆者も恐らくポテンシャルの三分の一も使えていません。
リンク先に「一か月でガチVIMMER」という記事がありますが、少なくともこの領域には達していません。

[新人達を1ヶ月でガチvimmerにした方法](https://qiita.com/nyantera/items/4bf29ca6f11bc797a9cb)

まあ、どういうカスタマイズが便利で、どんなコマンドを使いたいのかとなると、それは人によって変わってくるので、個々人で少しずつ使えるコマンドを増やしていくことが重要です。

 
#１．コマンド初歩の初歩

とりあえず最初は以下のコマンドだけは頑張って使いながら作業してみましょう。できるならば他にも使うコマンドを増やせばいいが、「一か月はこれだけを徹底的に使ってみる」というスタンスでも構わない…と思います。
 
・「iまたはo」と「ESC」
編集モードとコマンドモードの切り替え。これを使わないと何もできない。
 
・「:w」と「:q」
セーブと、VIMから抜けるコマンド。これもないと何もできない
 
・「hjkl」
上下左右への移動。方向キーを使うのは邪道だそうですが、多少そっちに手が行ってしまうのは仕方ない…と思う。
縛りプレイを徹底すれば上達は早まる。
 
・「yy」「dd」「p」
コピー、切り取り、貼り付け。行丸ごと対応してくれる。
これは無理してでも使いこなせるようになるべき。
ちなみに「数字＋yy」で指定した行数をコピーしてくれる（ddも同じ）
 
・「gg」「G」
最後尾行ないし、先頭行へワープ。
 
・「shift+v」または「ctrl+v」
複数行または一行の任意文字数を選択。その後yyなりddなりできる。
張り付ける位置には若干癖がある。

・「/（文字列）」と「n」
「/」から文字列を入力してエンターを押すと、文字列の場所にワープします。あとはnを押し続けると次の候補に飛んでいきます。

とりあえず、上記のコマンドを徹底的に使ってみること。あとは、自分のペースでできることを増やしていく。
 

#２．vimrcの設定
自分のルートディレクトリに「.vimrc」というファイルを作り、その中に好きな設定を書く。好みの設定は本当に人それぞれなので、以下のリンクあたりを参考にして取捨選択していけばいいです。
ただ、とりあえずは「set virtualedit=onemore」で、行末尾の一つ右までカーソルを移動できるようにしないと非常に不便だと思います。

[何も考えず~/.vimrcにこれを書くんだ！ 〜vim初心者によるvim初心者のためのvim入門〜](https://qiita.com/morikooooo/items/9fd41bcd8d1ce9170301)
No key No Object No Nested flat string value #JSON is valid format ? YES.

![image](https://user-images.githubusercontent.com/13635059/74287548-8f597500-4d6d-11ea-80d3-5f9ae93f96a7.png)
https://jsonformatter.curiousconcept.com/

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2981








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Rで量的データの概観を見る（ Descirbe() ）---初心者向け---

###### tags: `rBasicLearning`
# Describe()の使い方
### 使用するデータ
今回は, データとしてirisを使う.

```r
library(datasets)
iris
```
### Describe()を使う場合
量的データの概観の詳細を見たい時に使う.
### Describe()
以下のように, 量的データの, 母数・平均・標準偏差・メジアン・最大値・最小値・範囲・歪度・尖度・標準誤差が見れる.

```r
> describe(iris$Sepal.Length)  # One quantitative variable
   vars   n mean   sd median trimmed  mad min max range skew kurtosis   se
X1    1 150 5.84 0.83    5.8    5.81 1.04 4.3 7.9   3.6 0.31    -0.61 0.07
```

また, 以下のように全体を見ることもできる.
*がついているのは, 質的データ.

```r
> describe(iris)               # Entire data frame
             vars   n mean   sd median trimmed  mad min max range  skew kurtosis   se
Sepal.Length    1 150 5.84 0.83   5.80    5.81 1.04 4.3 7.9   3.6  0.31    -0.61 0.07
Sepal.Width     2 150 3.06 0.44   3.00    3.04 0.44 2.0 4.4   2.4  0.31     0.14 0.04
Petal.Length    3 150 3.76 1.77   4.35    3.76 1.85 1.0 6.9   5.9 -0.27    -1.42 0.14
Petal.Width     4 150 1.20 0.76   1.30    1.18 1.04 0.1 2.5   2.4 -0.10    -1.36 0.06
Species*        5 150 2.00 0.82   2.00    2.00 1.48 1.0 3.0   2.0  0.00    -1.52 0.07
```
永続ライセンス版Officeを32bitから64bitに変更するには

64bit版WindowsにOffice365またはOffice2019を新規インストールすると、明示的に32bitを指定しない限り、64bit版がインストールされるようになった。
マイクロソフトが64bit版を推奨すると方針転換したのは2019年以降なので、それ以前に導入したOfficeは、ほとんど32bit版になっていると思う。

ExcelマクロやAccessアプリをガシガシ使っているような現場の場合、組織内で、32bit版と64bit版が混在するのはトラブルの元である。
ということで、PCやOfficeを買い直すことなく、32bit版を64bit版に変更する方法を説明する。

なお、ひとつのPCで32bit版と64bit版の共存は出来ないため、64bit版をインストールする前に、32bit版をアンインストールしておく必要がある。

# Office365の場合
Office365で躓くことは先ず無いだろう。普通に再インストールすると64bit版が入るからだ。ただ、明示的にbit数を指定する手順は知っておくに越したことはないので一応解説しておく。
例えば、業者が納品した**コンパイル済ACCDE形式**のAccessアプリが32bitじゃないと動かないとかで、社内すべて32bitに寄せておきたいこともあるだろう。（筆者のお取引先でも過去にあった）

## インストールオプションの選択
https://portal.office.com にサインインし、[Officeのインストール] で [その他のインストールオプション] を選ぶ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/149eefac-0c7a-f8f3-dbfe-af0b0d891363.png)

## バージョンの変更
バージョンで64ビット／32ビットを選択し、[Officeのインストール] をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/c3f446f0-a38a-c5b6-f8b6-5823c9f859d4.png)

# 永続ライセンスの場合
Office2019は標準で64bitなので、**Office Professional 2016** での手順を説明する。
家庭向けOfficeのエディション（Home & Business）は試してないので分からない。

## プロダクトキーの入力
https://setup.office.com にサインインし、プロダクトキーを入力する。
ただし、アカウントにプロダクトキーが紐づいていれば、プロダクトキーの入力は求められない。

## ダウンロードURLの取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/7b3e2098-123e-097e-8426-670f801a8deb.png)
[今すぐダウンロード] を**右クリック**し、リンクURLを取得する。選択肢はブラウザによって異なるが、Chromeなら「リンクのアドレスをコピー」になる。

## URLの書き換え
URLに含まれる `platform=x86` を `platform=x64` に書き換えてアクセスすると、64bit版のインストールファイルがダウンロードできる。
まるで裏技だが、マイクロソフトの中の人も認めた手順なので安心して良い。

# 設定の引き継ぎについて
32bit版でカスタマイズした各種設定や「最近使ったアイテム」は、そのまま64bit版に引き継がれるようなので、すぐに使うことができた。

# VBAコードの影響
ExcelマクロやAccessアプリでbitに依存するコードというのは、外部ライブラリとリンクする場合である。
具体的には、**実行時バインディング**の`CreateObject`とか`Declare`宣言は見直した方が良い。**事前バインディング**の場合は参照設定を見直すことになる。
32bit版と64bit版のマクロを別々に作成するのはバージョン管理が大変になるので、コード内で処理を振り分けるのがスマートなやり方だ。

```visualbasic:例
#If Win64 Then
    strProvider = "Microsoft.ACE.OLEDB.12.0"  ' 64bit版OLEDBプロバイダ
#Else
    strProvider = "Microsoft.Jet.OLEDB.4.0"   ' 32bit版OLEDBプロバイダ
#End If
```
Gitの知識ゼロで現場に放り込まれた時は最低これだけおさえておけ！

「Gitについて何も知らないのに現場に放り込まれてしまった」

そんなことになったら、まず何をどうすればいいのか混乱することがほとんどだと思います。
コピペしてローカル環境でソースを修正しようとしたら「Cloneして作業してください」と言われてCloneとコピペの違いが分からなかったり、「コミットしてください」「プルしてください」と言われたところで何が行われているのか当然最初は分かりません。

Gitの入門書を見たり、ググってみたら漠然とどういう動作しているのかはわかるかもしれませんが、Gitの挙動は初学者ですと、少し調べただけでは何がどうなっているのか直感的には分かりにくいです。


さて、以下Gitを用いる開発現場に放り込まれた初学者は、とりあえず深いこと考えずに以下のことだけを、最低限の予習だと思って押さえてください。

当然これだけでは足りないですし、現場の運用方針やルールによっては他にも覚えるべきことは出て来ると思います。
しかし、取るものとりあえず以下のことだけ覚えておくのと、何も知らない状況ですと現場に入って作業にとりかかるまでのスピードと精神的安定感は全然違います。



#１．基本のコマンドは「add,commit,push,pull」のサイクルと「diff,status,checkout」
 
##基本は以下のサイクル

```
git add (ファイル名）
　ディレクトリ以下すべてをaddしたい場合「git add .」とする

git commit -m 'コメント'
　これでローカルリポジトリにコミットする

git push
　ローカルリポジトリにコミットしたものをリモートリポジトリに反映させる。
これで他の人がpullしたら自分の変更分を反映できる。

git pull
　他人がローカルリポジトリにコミットしたものを自分のところに反映させる。
``` 

##その他基本的なコマンド
```
・git reset
「addするのやっぱやめた」で最初は覚えておけばいい。

・git checkout（ファイル名　あるいは全部反映したいのなら「.」）
　作業中に、最後にpushないしpullした状態に戻したくなった時に使用するコマンド。
本来、もっと別の意味があるが、最初はそのような使い方でもいい。

・git diff
　addする前に打ち込むと、自分が変更した部分が出て来る。
これを見て自分が編集した覚えが無いものが上がっていた場合、自分のミスか、
あるいは他人の編集をデグレしてしまうことがあるため、
git resetでaddを取り消す。

・git status
　addした後、commitの前に入力すると、変更されたファイルが確認できる。
これを見て、リポジトリにあげたくないものがあった場合、git resetで取り消す。
```

#２．git initとgit clone、git remote -v
リモートリポジトリ（pushする先）をgit initで作成する。もし、複数の人が共有できるようにするならば「git init --bare --shared」と入力。
git initしたリポジトリを自分の開発環境でローカルリポジトリに持ってきて編集する場合は「git clone (パス)」を用いる。
また、ローカルリポジトリが、どこをcloneしたものか忘れた場合は「git remote -v」を用いればパスが表示される


 
#３．「.gitignore」ファイルを作ってリポジトリにあげたくないファイルを指定する

「git add .」とすればディレクトリ内のすべてがaddされてしまうし、いちいちあげたくないもの（特にIMGやデータファイルなど）は、gitignoreに正規表現で記入しておけば、add時に該当ファイルは対象外にしてくれる。




#これらは必要条件
以上、現場に入るときに最低限覚えておくべきことについてまとめました。
無論、上記のことは最低限ですので、もしかしたらもう少し求められる（ブランチ切るなど）こともあり得ます。ただ、ここで書いたことで無駄になるものは絶対ないですし、全部最低限必要条件ですので、身に着けておくべきです。
ここで書いてある用語でよくわからない言葉（「リモートリポジトリ」とか）は調べてみてください。


#まとめ—最低限覚えておいた方がいいコマンド
git add
git commit
git push
git pull
git reset
git checkout
git diff
git status
git remote
git init
git clone



その後、恐らくリポジトリ内に余計なファイルが管理されてしまうことがあると思います。その時に「いらないファイル消せ」と先輩に言われたときに「gitで登録されてるファイルってどうやって消すんだろう。えーと…そうか、『git rm』か」と言った感じで必要に応じて使えるものを増やしていきましょう。
React最低限の基礎メモ

Reactの勉強をしているのですが、仕組みの基礎理解が曖昧なので一度自分なりに最低限必要なところを整理したいと思います。

#御三家
とにかく覚えておかなければいけない三つ。

- component
- state
- props
 

これがわからないとコード書いてても何が何だかって感じでした。逆に言えばここさえわかれば大まかな流れは理解しやすいという印象です。

 

##component
ものすごくざっくり言えばページの各パーツです。

「メニュー」「テキスト入力フォーム」「ナビゲーション」みたいにそれぞれ役割が決まっているところをcomponentとして分けて設定していくといった感じでしょうか。

大抵は「components」というファイルを作成してそこに「menu.js」「navigation.js」「main.js」といった具合にページの各パーツのjsファイルを突っ込んでいきます。

これを組み合わせてindex.jsで表示させると言う流れです。

 

##state
「初期値」と認識するのがわかりやすいと思います。

例えば「＋ボタンを押すと表示されている数字が増える」といった機能を作りたいときは、カウントの最初の数値、つまり0をstateで設定します。

```
class Countor extends Component{
    constroctor(props){
        super(props);
        this.state={count:0};
    }
```

constroctorやsuperはstate作るときの定型文なんでとりあえずこのまま頭に入れてればおk。

このcountを0から増やしたい時には、stateの状態を変化させるsetStateを使います。

```

   handlePlusButton{
       this.setState({count:this.state.count+1})
   }
```

 

これで準備できたので、表示させるためにrenderとreturnでこいつらを設置してやります。

```
   render(){

      return(

         <div>

             <div>count:{this.state.count}</div>　　//初期値の0

             <button onClick={this.handlePlusButton}>   //ボタンを押すごとに1追加されていく

         </div>

      )

   }

}   //Countorの閉じ括弧

```

ざっくりですが、stateとsetStateの役割が理解できればなんとなく中身の完成イメージを想像しやすくなるので大事だと思いました。

##props
propsは「それぞれのデータを渡すもの」という認識です。

「props名=値」として使います。例えばメニューごとに表示内容を変えたい場合など、その表示データをpropsの値として設定すれば、違ったデータを表示することができます。

 

```
class Menu extends Component {
   render() {
       return (
          <div>
             <div>{this.props.name}</div>
          </div>
       );
   }
}

 

class App extends Component {
   render() {
      const menus=[
         {name:"pasta"},
         {name:"pizza"},
         {name:"juice"},
         {name:"coffee"}
      ]
      {menus.map((menu) => { 
         return (
            <Menu
               name={menu.name}
            />
          )

       })}
   }
}
```
 

この場合だとnameがprops名でpizzaやpastaといったものが値になります。

Menuコンポーネントにこれらのデータを渡してAppで表示しています。

 

正直propsの理解はまだだいぶ怪しいのですが、色々コードを打ってなれていきたいと思います。

 

 

#まとめ
とりあえずこの三つを押さえておけば、何をしているのか全体の流れはある程度理解できるのかなと思います。

まだまだReactには慣れないのですが、もう少し色々んあコードを打って理解を深めたいと思います。

 

お付き合いいただき有り難うございました。
VPC (Virtual Private Cloud) ~ AWS学習メモ ~ 

#VPCとは？

AWS上に仮想的なネットワークを構築しプライベートなクラウド環境を提供するサービス。
VPC領域を作成するとネットワークをEC2インスタンスなどを作成することができる。


##VPCの構成要素

構成の順番
１.AWSクラウド　→　2.リージョン　→　3.VPC　→　4.アベイラビリティ―ゾーン　
→　5.VPCサブネット（Public Subnet、Private Subnet）
<img width="548" alt="VPC1.0.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204606/7cad81d1-7595-c672-01e1-7d16637060fb.png">

##サブネット
・サブネットVPC内に構成するネットワークセグメントのことで、１つのVPCに対して１つ以上のサブネットで構成される。 
・Public Subnet、Private Subnetの違い 

【Public Subnet】
インターネットと直接通信を行う目的で作成されたサブネット（DMZ、Internet Facingとも呼ばれる）

【Private Subnet】
インターネット通信はせずに内部のみで通信する目的で作成されたサブネット

【IPアドレス】
IPアドレスはTCP/IPネットワーク上で、通信相手を識別するための番号です。

【CIDER(サイダー)　Classless Inter-Domain Routing】
クラスを使わないIPアドレスの割り当てと、経路選択（ルーティング）を柔軟に運用する技術。
IPアドレスのネットワーク部とホスト部を決めたられたブロック単位で区切る方法で、アドレス空間の利用に無駄が生じてしまう。これに対しクラスを使わないCIDRでは、任意のブロック単位で区切ることができるのでIPアドレス空間を効率的に利用することができる。

※最初の4IPと最後の1IPに関しては予約されているIPアドレスの為使用不可

##AWS Direct Connect
オンプレミス環境とAWSの間をつなぐ「接続ポイント」です。専用線を使用しているので高速で安定した通信を実現することができる。

##VPCピアリング
異なるVPC同士の通信をAWS内部で行うことができる。また異なるVPCにはいちしたEC2インスタンス間の通信やリージョンをまたいで通信することが可能。

##VPCエンドポイント
VPCエンドポイントには、ネットワークレイヤーのゲートウェイ型とアプリケーションレイヤーのインターフェイス型の2種類があります。
ゲートウェイ型では、ルートテーブルに指定されたターゲットを追加することでS3やDynamoDBへアクセスする際、インターネットを経由せずにAWS内のプライベート接続が可能。
インターフェイス型は、「AWS PrivateLink」とも呼ばれ、AWSへのAPIコールに対してインターネットを経由せずにプライベート接続を実現することができる。
Coq上で論理学を展開するとは？

数理論理学をCoq上でやると いいことがあるかもしれないという話です。

私のCoqの理解が進んできたのでとりあえず整理します。ツッコミ等も歓迎です。教養レベルの数理論理学の知識を前提とします。

## 1. メタ言語としてのCoq
**対象言語とは？**: 数理論理学で扱う対象は、構文規則に則った記号列（＝項や論理式）です。使える記号は前もって決めておきます。対象言語を定めるといいます。対象言語を定めることで対象を正確に記述できます。

**メタ言語とは？**: 一方、論理式同士に成り立つ秩序（例: 推論, 証明, 帰結関係, 理論の各種性質）は、日本語や英語などの自然言語、対象言語の記号、及び、対象言語に含まれない記号を使って定式化されます。対象言語に言及しつつ、その性質を対象言語の外から眺めて読者を納得に導く言語をメタ言語といいます。

**メタな論理は自明なのか？**: メタ言語でなされる行為や規則には、それを支える論理があります。多くの場合 自明すぎて明示されませんが、問題になることもあります。以下のような疑問を持った人も多いと思います:

- 意味論において集合概念を利用するのは循環的であり、問題はないのか？
   - 集合論を基礎づけるための数理論理の説明に、集合論的な概念がでてくるという意味での「循環」です
- 1階述語論理の完全性の証明に 選択公理を使って本当によいのか？
- そもそも、その説明はどのような論理・規則で正当化されているのか？
   - 例えば [亀がアキレスに言ったこと-Wikipedia](https://ja.wikipedia.org/wiki/%E4%BA%80%E3%81%8C%E3%82%A2%E3%82%AD%E3%83%AC%E3%82%B9%E3%81%AB%E8%A8%80%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8) に代表されるように無限後退は生じないのだろうか？
- そもそも、その説明は一意に解釈可能な意味を持っているのか？
    - 後期ウィトゲンシュタインの哲学に代表される問題意識を持つ必要はどうしても出てきます。

このように、数理論理学の主戦場であるメタレベルにおける行為は、（人間にとって）誤りやすい、前提や仮定や規則が明示化/一覧化されていない、という側面を持つといってもいいかもしれません。

**メタ言語としてのCoq**: 証明や推論は規則に従った行為であるので、コンピュータに代行させることも可能です。より正確には、コンピュータにある種の情報処理をさせることができ、人間がその入出力に対して推論や証明をしているという意味付けできます。こうすることで、人間が陥るケアレスミスを防いだり、必要な前提を明確化できるなどのメリットがあります。Coqはそのための道具立てを提供します。

**本節のまとめ**: 数理論理学における証明や推論といった行為は、コンピュータでも可能です。Coqを使ってコンピュータにやらせることで、ケアレスミスを防止したり、メタレベルでの前提・仮定を明確化できたり、成果物を実行環境ごと保存ができたりして、いいことずくめのような気がします。

## 2. Coqとは結局何なのか？
**Coqとは何か？**: CoqとはCIC/Calclus of Inductive Constructionという計算体系をコンピュータ上で実行するための一連の道具立てです。「論理」と「計算」は異なりますが、カリーハワード対応に見られるように 密接な関係もあります。CICはカリーハワード対応を積極的に採用・拡張した体系です。そしてCoq/CICは、（命題や証明のカリーハワード対応物である）型や証明項を扱う型システムであるだけでなく（型システムからみた対応物である）命題を体系に組み込んでいます(Propというimpredicativeなソートが組み込まれています)。その意味で Coq では命題や証明を直接扱っているともいえます。

**Coqで論理学を符号化**: 上述のようにCoqは、命題や証明を扱えますが、その一方で、Coq/CICは計算体系であり論理そのものではありません。なので、Coq/CIC をメタ言語として採用して数理論理学を展開する、という目的のためには、Coq/CICで組み込まれているPropを使うのではなく、論理学を一から構成する必要があります。例えば、[有名なゲーデルの不完全性定理をCoq上で証明した成果](https://github.com/coq-contribs/goedel) では、1階述語論理およびペアノ算術における対象言語の符号化、及び、それらへのメタな行為（例: 置換、証明、表現可能性）を符号化しています。CICはそれ自体では自然数もブール値も含んでいないので 一から構成しますが、論理学もそれにならうということです。

**Coqはどこまで柔軟か？**: 数理論理学のメタ言語は日本語・英語などの自然言語ですが、これをCoqで代替できるほどCoqは柔軟で表現力が高い体系なのでしょうか？答えは恐らくYesです。CICはその名前が示すように構成的な道具立てで排中律が成立しないなどの性質もありますが、排中律を計算体系に組み込むこと（≒公理とすること）は簡単にできますし、その他の公理を組み込むことも簡単です（もちろん好き勝手に足すとCICが矛盾をきたすので程々が大事でしょうが・・）。注：ここでの排中律の例はメタ言語としての話です。符号化された古典論理において排中律が成立するかはそのように作ればよいだけの話です。なお、必ず停止するという性質は、こと証明に関して言えば、証明とは有限長であることから好ましい性質です。

## 3. 最後に
Coq上で論理学を展開することの概念図を書いて、記事を締めます:

```
<普通の数理論理学>
対象レベル: 対象言語の記号列。例: 0+S0=S0 
メタレベル: 自然言語。例: 0+S0=S0は証明可能である

<算術化した数理論理学>
対象レベル: 算術の言語の記号列のゲーデル数
メタレベル: メタレベルの行為/言明のゲーデル数, 及びそれを数項として持つ論理式のゲーデル数（の数項を持つ論理式のゲーデル数（の数項を持つ・・・・）
メタメタレベル: 自然言語　例: ゲーデル数の復号・解釈

<Coqビルトインの論理学>
対象レベル: Propをソートとするobject
メタレベル: タクティックをつかった証明項の構成

<Coqをメタに使った数理論理学>
対象レベル: CICでのデータ型。例: Term型 Formula型
メタレベル: CICでのデータ型・Fixpoint・型つけ。例: SysPrf型（ヒルベルト流証明型）
```
StackEditのmermaidを更新してみた

# 概要
[StackEdit](https://stackedit.io/)は[mermaid](https://mermaid-js.github.io/mermaid/#/)でフローチャートシーケンス図を描画している。
このmermaidのバージョンが古いせいか、他の図（クラス図とか）を表示してくれない。
そこで、StackEditのmermaidのバージョンを更新してみた。

# mermaidのバージョン
StackEditで使われているmermaidは[8.0.0-rc.8](https://github.com/benweet/stackedit/blob/2fdbb67c67159c4ccfddbe51fc9303c6c799dbe0/package.json#L53)だった。
雑に調べたところ、[8.1でクラス図を表示できるようになった](https://github.com/mermaid-js/mermaid/issues/858)とあったので、
mermaidを新しくすればStackEditでもクラス図が表示されるはず（願望）。

# StackEditのmermaidを更新

[mermaidを更新したものがこちらになります(プルリク)](https://github.com/benweet/stackedit/pull/1590)

<img width="1437" alt="スクリーンショット 2020-02-13 7.17.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32410/10855457-69d4-8b24-b0f3-b8c841ee11ce.png">

クラス図が表示されました :sunglasses:

# 起動方法 (Mac)
開発サーバーの起動方法
※nodeとかnpm入っている前提です。

```bash
git clone -b update-mermaid https://github.com/vienai8d/stackedit.git
cd stackedit
npm install
npm start
open http://localhost:8080
```

# 新たな課題

プルリクしてみたもののマージされる気配がない
↓
localhostで起動したStackEditを使ってみる
↓
同期機能や投稿機能が使えない
↓
:thinking: 

いろいろ模索した結果、
**GCPでStackEdit建ててみたらもろもろ解決した** :sunglasses: 

その詳細は次の投稿で紹介します。
→ [GCPでオレオレStackEditを建ててみた](https://qiita.com/vienai8d/items/8049836334016afc09d9)
RMSpropGravesについて自分なりに考えてみた

オプティマイザについてSGDやRMSprop、Adadelta、Adamなどの解説記事を読むと、どういう工夫がなされているのかなんとなく分かります。しかし、RMSpropGravesについては提案した論文にも詳しい説明はなく、解説記事もほとんど見つかりません。そこで自分なりに考えてみました。

間違っていたら恥ずかしいので指摘してください。

RMSpropGravesの最適化手法は以下の式で表される。

```math
   {g}^{(t)}=\nabla E({w}^{(t)})\\
```
```math
   {m}_t=\rho_1{m}_{t-1}+(1-\rho_1){g}^{(t)}\\
```
```math
   {v}_t=\rho_2{v}_{t-1}+(1-\rho_２)({g}^{(t)})^2\\
```
```math
   \Delta{w}^{(t)}=-\frac{\eta}{\sqrt{{v}_t-{m}_t^2+\varepsilon}}{g}^{(t)}\\
```
```math
   {w}^{(t+1)}={w}^{(t)}+\Delta{w}^{(t)}
```
　RMSpropGravesはモーメンタム項を考慮することも多く、その場合は以下のようになる。

```math
   \Delta{w}^{(t)}=-\mu\Delta{w}^{(t-1)}-\frac{\eta}{\sqrt{{v}_t-{m}_t^2+\varepsilon}}{g}^{(t)}\\
```

　ここで ${m}_0=0$、${v}_0=0$ と初期値を設定すると、

```math
   {m}_t=(1-\rho_1)\sum_{i=1}^{t}\rho_1^{t-i}{g}^{(i)}
```

```math
   {v}_t=(1-\rho_2)\sum_{i=1}^{t}\rho_2^{t-i}({g}^{(i)})^2
```
 　ここで議論をわかりやすくするために、$i=1\sim t$に対しベクトル${g}^{(i)}$の単位ベクトルを基底ベクトルとした座標変換を考え、${m}_t$ を$\underline{{m}_t}$、${v}_t$を$\underline{{v}_t}$と座標変換する。また各要素に大きさ$\|{g}^{(i)}\|$をもつベクトルを$\underline{{g}^{(t)}}$とする。

```math
   {v}_t=(1-\rho_2)\sum_{i=1}^{t}\rho_2^{t-i}({g}^{(i)})^2=\underline{{g}^{(t)}}\odot\underline{{m}_t}
```

```math
   {v}_t-{{m}_t}^2 =\underline{{g}^{(t)}}\odot\underline{{m}_t}-\underline{{m}_t}\odot\underline{{m}_t}=(\underline{{g}^{(t)}}-\underline{{m}_t})\odot\underline{{m}_t}
```

 RMSpropとRMSpropGravesの違いは$\Delta{w}^{(t)}$を求める際に、${v}_t$が${v}_t-{m}_t^2$となっている点である。この意味は$\underline{{g}}^{(t)}$を$\underline{{g}^{(t)}}-\underline{{m}_t}$と修正していることが上の式より分かる。よっては$\Delta{w}^{(t)}$の更新において勾配に掛けられる係数はRMSpropよりも大きくなることがわかる。
 
 これは直近に取得した勾配の影響を抑える働きがある。具体的には$\underline{{g}}-\underline{{m}_t}$の最新の要素$i=t$に対して、

```math
   (\underline{{g}^{(t)}}-\underline{{m}_t})_{t}={g}^{(t)}-(1-\rho_1){g}^{(t)}=\rho_1{g}^{(t)}
```

 となり、$0<\rho_1<1$であるため$\rho_1$だけ抑えらていることがわかる。
 逆に、最も古い勾配は$i=1$で$t\rightarrow\infty$において

```math
   (\underline{{g}^{(t)}}-\underline{{m}_t})_{1}=\lim_{t \to \infty}\left({g}^{(1)}-(1-\rho_1)\rho_1^{t-1}{g}^{(1)}\right)={g}^{(1)}
```

 となり、古い勾配であるほど補正の影響がなくなることがわかる。
tkinterを別スレッドで起動したときは、そのスレッド自身で停止処理して変数を後始末してからスレッド終了すること

tkinterを別スレッドで起動した際、プログラムを正常終了させるのに苦労したので情報共有します。

tkinterは`mainloop()`を呼び出すことで、描画処理やイベント処理をループします。
tkinterの`destroy()`を呼び出すことで、`mainloop()`を終了させることができます。
その後、スレッド終了する際にtkinterの破棄処理も行われます。

ただし、別スレッドから `destroy()` を呼び出したり、tkinterウィジェット(GUI部品)がインスタンス変数に代入されたままになっていたりすると、プログラムを正常終了することができませんでした。

サンプルプログラムで説明します。

```py
import time
import threading
import tkinter as tk


class GUI:

    def start(self):
        self.running = True
        self.window = tk.Tk()
        self.window.title("Sample")
        self.window.geometry('320x240')

        self.value = tk.StringVar()
        entry = tk.Entry(textvariable=self.value)
        entry.pack()

        self.window.after(1000, self._check_to_quit)
        self.window.mainloop()
        # need to delete variables that reference tkinter objects in the thread
        del self.value
        del self.window

    def _check_to_quit(self):
        if self.running:
            self.window.after(1000, self._check_to_quit)
        else:
            self.window.destroy()

    def quit(self):
        self.running = False


def main():
    gui = GUI()
    thread = threading.Thread(target=gui.start)
    thread.start()

    time.sleep(2)
    for i in 1, 2, 3, 'ダー!!':
        gui.value.set(i)
        time.sleep(1)

    gui.quit()
    thread.join()

if __name__ == '__main__':
    main()
```

`main()`で、guiとサブスレッドを生成し、サブスレッドで`gui.start()`を起動しています。

`main()` 処理を終了する際、`gui.quit()`を呼び出して終了フラグをセットし、サブスレッドが1秒間隔でチェックして、サブスレッド自らが`destroy()`を呼び出すようにしています。
この `gui.quit()` の代わりに、直接 `gui.window.destroy()` を呼び出すと無限ループに陥りました。
`CTRL+C`もきかず、`CTRL+\` で強制終了させる（コアダンプさせる）しかありませんでした。

サブスレッドでは、`mainloop()` から抜けてきた後、インスタンス変数を `del` しています。
この `del` 処理を行わないと、プログラムが異常終了（コアダンプ）したり、エラーメッセージを延々と出力し続けたりしました。

`main()`から直接`gui.window.destroy()`したり、インスタンス変数のdel処理をコメントアウトしたりして、何がおきるか実験してみてください。

tkinterとスレッドを併用する際には注意しましょう。
AppleScript  で 簡単カンマ入れ

198,000 など、3桁ごとにカンマを入れるのがめんどくさかったので、ごくごく簡単に作ってみました。

```applescript
set thePrice to 198000 as string

set AppleScript's text item delimiters to ""

set thePrice to every character of thePrice

repeat with i from (count of thePrice) - 3 to 1 by -3
	set item i of thePrice to (item i of thePrice & ",") as string
end repeat

display dialog (thePrice as string)
```

ハンドラで使用する場合は

```applescript

display dialog (makeComma(198000 as string))

on makeComma(thePrice)
	
	set AppleScript's text item delimiters to ""
	
	set thePrice to every character of thePrice
	
	repeat with i from (count of thePrice) - 3 to 1 by -3
		set item i of thePrice to (item i of thePrice & ",") as string
	end repeat
	
	return thePrice as string
	
end makeComma
```

現状では整数のみで小数点には対応していませんが、ひとまず。
構造化データの読み込みにまつわる問題 〜evalインジェクション〜

XMLやJSONなどの構造を持つデータを保存や送受信できるように変換することをシリアライズと呼ぶ。
シリアライズは配列データを配列データとして保存できたりなど、配列の要素や構造が動的に変化するデータを扱う際などに使用される。
ここではシリアライズに関する脆弱性の一つであるevalインジェクションについて記載する。

#概要
プログラム言語にはevalと呼ばれる関数・機能があり、これは文字列（各言語のコード）を式として評価したのものである。
evalは使い方によって外部から送り込んだスクリプトが実行されることがある。
それをevalインジェクション攻撃と言い、そのような攻撃を受ける脆弱性をevalインジェクション脆弱性と呼ぶ。

###evalの例
**JavaScript**[（MDN）](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval)
>eval(string)

**PHP**[（php.net）](https://www.php.net/manual/ja/function.eval.php)
>eval ( string $code ) : mixed

evalインジェクションによる影響は以下のOSコマンド・インジェクション攻撃と同じ。

- 情報漏洩
- サイト改ざん
- 不正な機能実行
- 他サイトへの攻撃（踏み台）
- 暗号通貨の採掘（マイニング）

evalインジェクション脆弱性の対策は以下の通り

- evalに相当する機能を使わない
- evalの引数には外部からのパラメータを含めない
- evalに与える外部からのパラメータを英数字に限定する

#攻撃手法と影響
シリアライズしてフォーム間を受け渡す場合の脆弱性について。
例としてPHPのvar_export関数を使ってシリアライズした後にbase64にエンコードしデータを受け渡す。受け渡されたデータのbase64をデコードし、evalを用いて元のデータに戻す（デシリアライズする）とする。
[参考イメージ](https://hijiriworld.com/web/serialize/)

```4e-001.php
<?php
  $a = array(1, 2, 3);
  $ex = var_export($a, true);
  $b64 = base64_encode($ex);
?>
<body>
<form action="4e-002.php" method="GET">
<input type="hidden" name="data" value="<?php echo htmlspecialchars($b64) ?>">
<input type="submit" value="次へ">
</form>
</body>
```

```4e-002.php
<?php
  $data = $_GET['data'];
  $str = base64_decode($data);
  eval('$a = ' . $str . ';');
?>
<body>
<?php var_dump($a); ?>
</body>
```
##攻撃手法
evalに渡す式に任意の文を追加（スクリプトを注入）する。
>$a = 式: 任意の文;

>$a = 0: phpinfo();

OWASP ZAPで上記を試すとphpinfoが表示され、外部から注入したスクリプトが実行された状態となる。
これらの事例から情報漏洩やサイト改ざんなどの影響を受ける可能性がある。

#脆弱性が生まれる原因
evalに与えるパラメータをチェックしていないため。
PHPであれば任意のコードを実行できてしまうようにevalはそもそも危険な言語構造であること。 

**evalインジェクション脆弱性の原因は以下の通り。**

- evalを用いることがそもそも危険
- evalに与えるパラメータのチェックがされていない

#対策
**evalインジェクション脆弱性の対策は以下の通り。**

- eval（同等機能含む）を使わない
- evalの引数に外部からのパラメータを指定しない
- evalの与える外部からのパラメータを英数字に制限する

##evalを使わない
eval（同等機能含む）を使わず、eval以外の選択肢を検討する。
シリアライズが目的であれば以下の選択肢がある。

- [implode](https://www.php.net/manual/ja/function.implode.php) / [explode](https://www.php.net/manual/ja/function.explode.php)
- [json_encode](https://www.php.net/manual/ja/function.json-encode.php) / [json_decode](https://www.php.net/manual/ja/function.json-decode.php)
- [serialize](https://www.php.net/manual/ja/function.serialize.php) / [unserialize](https://www.php.net/manual/ja/function.unserialize.php)

シリアライズ以外の目的でもevalは極力使わない実装を検討する。
evalを使わずに同等の処理は実装可能。

##evalの引数に外部からのパラメータを指定しな
evalを使った場合でも外部からパラメータを指定しない。
外部からスクリプトを注入できなくすれば安全だが、注入経路がファイルやデータベースの場合この対策は使えない。

##evalに与える外部からのパラメータを英数字に制限する
外部から与えるパラメータを英数字に限定できればスクリプト注入に必要な記号文字を使えなくすることができる。
正規表現による入力値検証などを行う。

#まとめ
evalを使わない実装を行う。
どうしてもevalを使わなければならない場合は外部からのスクリプト注入を防ぐ対策を行う。

#さらに進んだ学習のために
[phpMyAdminに存在したpreg_replaceによるコード実行脆弱性の実例](https://blog.tokumaru.org/2013/05/phpMyAdmin3.5.8-script-injection-CVE-2013-3238.html)
[Jest]TypeError: Cannot read property 'readFileSync' of null

#Overview

Jestでテストを実行した際、以下のエラーに遭遇しましたか？
もしあなたがesmのパッケージを利用しているなら、私はその問題の緩和策を提示できるでしょう。

```terminal
TypeError: Cannot read property 'readFileSync' of null

      at fetch (node_modules/protobufjs/src/root.js:160:34)
      at Root.load (node_modules/protobufjs/src/root.js:194:13)
      at Root.loadSync (node_modules/protobufjs/src/root.js:235:17)
      at Object.loadSync (node_modules/protobufjs/src/index-light.js:69:17)
      at Object.<anonymous> (node_modules/@grpc/proto-loader/build/src/index.js:235:37)

```

#Target reader

- 前述のエラーに遭遇した方。

#Prerequisite

- Node.js v10.19.0
- esmパッケージを利用している


#Body

##Jestとesmの関係について少しだけ言及

Jestはimport/exportの形式に執筆時点では対応していない。
つまりimport/exportの記述を可能にするesmとは相性が悪い。
その辺について知りたい場合は別記事を参照してください。
https://qiita.com/qrusadorz/items/f637953c0ada73483700#esm%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E6%B3%A8%E6%84%8F%E7%82%B9

esmをnodeコマンドで実行したり、サーバーレスのFunctionsで実行する分には問題ない。
それは私自身esmを実際に導入を完了しており、事実に基づいた発言である。
しかし、Jestだけはどうしてもだめだった:joy:

一応今回の問題はissueには上がっている。
https://github.com/standard-things/esm/issues/779

微妙に違うように見えるかもしれないが根本原因は一緒だと考えている。
恐らくこの問題は当分の間は解決されないだろうから、緩和策を模索した。

##import文をあきらめる

人間引き際の判断が大事。幸いesmはrequireを混在して使ってもOKなので、エラーの発生する該当ソースはrequireのままにしておく。
本番ならそれだけでOKだが、Jestはesmの先にいるエラーが発生するパッケージのrequireを許してくれない:laughing:
想像になるが、各テストのソースコード冒頭に置く```const requireEsm = require('esm')(module);
```がrequireを置き換え、Jest環境下ではうまく行かないのだろう。

この考えのもと回避処理を作るとうまく行く。
まずはエラーが発生するテストコードの一行目を次のようにする。

```javascript:hoge.test.js
global.requireJest = require; // ★esmが置き換える前のもとのrequireを保存しておく

// 通常はここが1行目で、esmのrequireを使用するだけでOK。
const requireEsm = require('esm')(module);
const { objectToArray } = requireEsm('../../utils/object')
```

ネーミングは重複しないなら何でもいいが、ここではrequireJestとして本来のrequireをglobalに保存する。
次にエラーが発生するimport部分に対応を入れる。
実際にエラーが発生したfirebase-adminのパッケージに対応した例を掲載する。

```javascript:firebaseAdmin.js
// import admin from 'firebase-admin'; // 残念ながらJestではエラーになる
const admin = global.requireJest ? requireJest('firebase-admin') : require('firebase-admin'); // for jest test
```

前述で```global.requireJest```に保存したrequireがあるならそちらを利用し、ないなら本番環境なので通常のrequireを使用する。
これで本番でもJestでもどちらでも動くことが可能。

#Conclusion

esmによりimport/exportが使用可能になり便利だが、最後にJestの落とし穴がある。
その箇所だけimportをあきらめれば完遂できるので、あきらめちゃだめだという話でした。

ちなみに私が一気に移行した際、firebaseAdmin.jsを参照しているテストが全てダメになった。
スタックトレースからはfirebaseAdmin.jsで発生したというのが不明のため、判明するのに時間かかりました。
（ちまちまスタブに置き換えてimport文一つ一つ探した:sob:）

Have a great day!
辞書のitemsメソッド

```python:items.py
num = {'x':100, 'y':200}
print(num.items())

#辞書をfor文で処理するとキーが返ってくる
for k in num:
    print(k)
    
#値が欲しい場合は、valuesメソッドを使う
for v in num.values():
    print(v)

#キーと値のペアが欲しい場合は、itemsメソッドを使う
#for文で処理するとk,vにそれぞれキーと値が入る(タプルのアンパッキング)
for k, v in num.items():
    print(k, ':', v)
```
出力結果：

```
dict_items([('x', 100), ('y', 200)])
x
y
100
200
x : 100
y : 200
```
CreateObjectでよく使用するオブジェクト一覧

# 目的
- クラスモジュールなどを作成する際、事前バインディングを利用すると、あとで流用する時に参照設定漏れなどで不具合の元になるため、個人的に実行時バインディングで記入することが多い。  
そのため、必要になる処理を備忘＋コピー&ペースト用に整理する。

# オブジェクトの参照方法について
呼び出し方法によってインスタンスの生成タイミングが異なるため、
状況によっては注意が必要。

## Set = での宣言
```VB
Dim obj As Object
Set obj = CreateObject("Scripting.FileSystemObject")
' ~~~ 処理 ~~~
MsgBox obj.GetFolder("C:\temp").Files.Count
' ~~~~~~~~~~~~
Set obj = Nothing
```
Setで代入した際にインスタンスが生成される。

## With での宣言
```VB
With CreateObject("Scripting.FileSystemObject")
' ~~~ 処理 ~~~
    MsgBox .GetFolder("C:\temp").Files.Count
' ~~~~~~~~~~~~
End With
```
With内で最初に呼び出されたメソッド、プロパティ利用時にインスタンスが生成される。

# 実行時バインディング 一覧
参照設定|class(CreateObject)|オブジェクト式(As,New)
:-:|:-:|:-:
Microsoft Access X.X Object Library|Access.Application|Access.Application
Microsoft Excel X.X Object Library|Excel.Application|Excel.Application
Microsoft Word X.X Object Library|Word.Application|Word.Application
Microsoft Word X.X Object Library|Word.Document|Word.Document
Microsoft PowerPoint X.X Object Library|PowerPoint.Application|PowerPoint.Application
Microsoft Outlook X.X Object Library|Outlook.Application|Outlook.Application
Microsoft CDO for Windows 2000 Library|CDO.Message|CDO.Message
Microsoft Internet Controls|InternetExplorer.Application|InternetExplorer
Microsoft HTML Object Library|htmlfile|HTMLDocument
Microsoft XML, vX.X|MSXML2.XMLHTTP  XMLHTTP60 …Windows10|MSXML2.XMLHTTP
Microsoft ActiveX Data Objects X.X Library|ADODB.Connection|	ADODB.Connection
Microsoft ActiveX Data Objects X.X Library|ADODB.Recordset|ADODB.Recordset
Microsoft ActiveX Data Objects X.X Library|ADODB.Stream|ADODB.Stream
Microsoft DAO 3.6 Object Library|DAO.DBEngine.120|DAO.DBEngine
Microsoft Forms 2.0 Object Library|new:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}|MSForms.DataObject
Microsoft Scripting Runtime|Scripting.Dictionary|Dictionary
Microsoft Scripting Runtime|Scripting.FileSystemObject|FileSystemObject
Windows Script Host Object Model|Wscript.Shell|WshShell
Microsoft Shell Controls And Automation|Shell.Application|Shell32.Shell
Microsoft VBScript Regular Expressions X.X|VBScript.RegExp|RegExp
Microsoft WMI Scripting VX.X Library|WbemScripting.SWbemLocator|WbemScripting.SWbemLocator

# 参考サイト
[参照設定、CreateObject、オブジェクト式の一覧](https://excel-ubara.com/excelvba4/EXCEL296.html)
[参照設定とCreateObjectの対応リスト](http://www.thom.jp/vbainfo/refsetting.html)
クローンしたリポジトリ、submoduleの中身が空っぽだった！

# git submodule update ができない

### 問題点

submoduleを含むgitのリポジトリをクローンしたが、submoduleの中身が空っぽだった。
そこで git submodule update をしてみたが、

```terminal
$ git submodule update

Please make sure you have the correct access rights and the repository exists.
fatal: clone of '[shhのキー]' into submodule path '[ローカルのパス]' failed 
Failed to clone '[submoduleのリポジトリ]'. 
Retry scheduled Cloning into '[ローカルのパス]'...
Host key verification failed.
fatal: Could not read from remote repository.
```
以下のようなログが返ってきた。

### 解決策 `.git/config`を書き換える

`.git/config`内のsubmodule部分のurlをsshからhttpsに変更する。

----

```:.git/config
[submodule "サブモジュール名"]
	url = git@gitlab.com:******* # ssh
```

この部分を書き換える。

```:.git/config
[submodule "サブモジュール名"]
	url = https://gitlab.com/****** # https
```

---

別の解決策としてSSHの公開鍵を登録する方法もあります。

今回は`.git/config`を書き換えて`git submodule update` をしたら、
空っぽだったsubmoduleのフォルダにsubmoduleのプログラムを導入することができました。

submoduleを使いこなせるようになりたいものです。以上！

## 参考
* https://kagasu.hatenablog.com/entry/2019/05/17/002443
[漏洞分析]CVE-2019-17564/Apache Dubbo存在反序列化漏洞

### 漏洞描述
`Apache Dubbo`支持多种协议,官方推荐使用`Dubbo`协议.`Apache Dubbo HTTP`协议中的一个反序列化漏洞（CVE-2019-17564）,该漏洞的主要原因在于当`Apache Dubbo`启用`HTTP`协议之后，`Apache Dubbo`对消息体处理不当导致不安全反序列化，当项目包中存在可用的`gadgets`时即可导致远程代码执行.
### CVE编号
CVE-2020-17564
### 漏洞威胁等级
高危
### 影响范围
2.7.0 <= Apache Dubbo <= 2.7.4.1
2.6.0 <= Apache Dubbo <= 2.6.7
Apache Dubbo = 2.5.x
### 漏洞分析
- 1.环境搭建

为了环境搭建方便，访问`dubbo-samples`的github项目主页(https://github.com/apache/dubbo-samples)

下载源码以后,分离出http部分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/daed29cd-f3ce-3801-88db-737386686305.png)

修改pom.xml中32行`dubbo.version`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/5c7c4b04-880b-4153-79ef-c95997f8314c.png)

修改其为漏洞版本,以2.7.3为例,随后在Idea中开启即可
修改JDK版本为1.8

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/0c2c2211-3760-7ef3-bef1-30c3606c8054.png)

随后导入一个可控的gadgets用于分析,例如`commons-collections4-4.0`,并启动`HttpProvider`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/518600da-3d63-82c9-92eb-bc1535674b5d.png)

##### 注:Dubbo启动依赖zookeeper,这部分使用不再赘述,请自行查阅google
- 2.漏洞分析

我们进入`org.apache.dubbo.remoting.http.servlet.DispatcherServlet`在43行`handler.handle(request, response);`处打入断点，利用burp进行发包跟踪它的走向

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/7063e172-e3cf-8422-200d-7b1bfe793c3f.png)

随后发现其进入`org.apache.dubbo.rpc.protocol.http.HttpProtocol`中的`handle`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/f730054a-b2d2-971d-6ffc-31cec0da5240.png)

进一步跟踪

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/5b988fc7-59f6-2944-f551-387535aa08c5.png)

最终进入`org.springframework.remoting.rmi.RemoteInvocationSerializingExporter`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/52d42953-2929-9b56-66ec-509d55431551.png)

该ois对象来源为报文中post data部分,对于传入的ois并没有做任何安全过滤和检查,直接就行了`readObject`方法导致RCE产生.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/28fc2629-5b17-3b8b-7fd6-bb100aac8d57.png)

很多人不太理解Java反序列化漏洞怎么rce,这里给出一段示例代码

使用`ysoserial`随意生成一个序列化文件,再利用下面的代码读取该序列化文件即可达到效果,可见直接使用`readObject`方法的危害

```
import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class test1 {
    public test1() {
    }

    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("/Users/xue/Documents/NetSafe/Tools/JavaTools/1.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        ois.readObject();
    }
}
```
### 漏洞验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/2dc00128-02c4-3ad4-0c5f-a02b24106b4c.png)
### 修复建议
升级Apache Dubbo到2.7.5版本
### 时间轴
[0] 2020/02/10 该漏洞披露邮件公开
[1] 2020/02/13 亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞分析
### Reference
https://www.mail-archive.com/dev@dubbo.apache.org/msg06225.html
multipassを使って暴速でkubernetes（microk8s）環境を作る

# Why

[multipass](https://multipass.run/) を使って [microk8s](https://microk8s.io/) 環境を作ればマルチプラットフォームで kubernetes のテスト環境を手早く構築できる。
でもいつも `zsh/oh-my-zsh/powerlevel10k` のCLI環境で作業している自分にとって素のbashがとても使いにくい。
それに `kubectl` のcompletionやもろもろのツールのインストールや設定が面倒

そこで、multipass では`--cloud-init`フラグで [cloud-init](https://cloud-init.io/) が使えるので、これを使用してプロビジョニングする。

（あ…これ全部 [canonical](https://canonical.com) のプロダクトやん）

# Prerequisite（前提条件）

各環境に合わせて multipass をインストールしてください。
リンク: https://multipass.run/docs

# TL;DR

適当なディレクトリに移動して以下のコマンドを実行すれば環境構築完了です。

```
$ wget https://raw.githubusercontent.com/cashewnuts/multipass-env/master/microk8s/cloud-config.yaml
$ multipass launch -n microk8s-vm --cloud-init cloud-config.yaml --mem 4G --disk 40G
```

# 用語解説

### multipass
ローカルにlinuxインスタンスを作成するツール
いつでも最新のubuntu環境を気軽に試せて、ホストのファイルシステムのマウントも簡単にできる。

Windows Subsystem for Linux のマルチプラットフォーム版、あるいは Docker を普段使い用にお手軽にしたようなツール

### microk8s
kubernetes の環境をまるごと1つのパッケージとしてまとめたもの

### cloud-init
クラウドインスタンス（AWSのEC2など）のプロビジョニング方法としてデファクトスタンダードとなっているツール
ほとんどのIaaS のクラウドプロバイダーでは cloud-init を使ったプロビジョニング方法を用意している。
デファクトの割にドキュメントが充実してない。

# cloud-config.yamlの解説
追記予定

# 成果物
うまくいくと以下のように`zsh`やもろもろのツールを含むCLI環境が構築された microk8s 用インスタンスが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308122/6b168a97-8182-7b47-3110-bc983aabdfa6.png)


このソース（？）は github 上にあります。
https://github.com/cashewnuts/multipass-env

# 以下メモ書き
## cloud-init のデバッグ方法
cloud-init のデバッグの仕方がよくわからなくて苦労した。

結論として、`multipass shell <instance-name>`でログインしたあと以下のファイルを見ることで、どこで失敗したのかが確認できた。

```
# cloud-initが内部で実行しているpythonのデバッグログ
/var/log/cloud-init.log
# cloud-initの設定ファイル(yaml)をもとに実行されたbashスクリプトのログ
/var/log/cloud-init-output.log
```
音楽ファイル(flac, wav)のタグ情報(タイトルやアーティスト)を抽出したい。

# 初めに
ハイレゾ音源しかもってないためmp3とか知りません。FLACやWAVEのタグ情報（曲名やアーティスト）を取得したいのです。
mutagenライブラリでは、wav形式の音楽ファイルのタグ情報が取得できなかったため、pytaglibライブラリを使用しました。

## PC環境
windows10 pro 64bit
python 3.8.1 64bit

# pytaglibをinstallする
pytaglibはTagLibというC++ライブラリをバインドしてpythonから動作するようにしたライブラリ。

### Windowsは「pip install pytaglib」ではダメ
以下公式の下のほうにある「Manual Compilation: Windows」を実施した。
[pytaglib公式](https://pypi.org/project/pytaglib/)

### 準備
TagLibをダウンロードして解凍しておく。
(https://taglib.org/#windows)

### 手順１
~~~
1. Install Microsoft Visual Studio 2015 Community Edition. In the installation process, be sure to enable C/C++ support. Alternatively, install Visual Studio 2017, but install the "v140" C++ toolset and use the "Visual Studio 2015" version of the developer command prompt below.
~~~
C++のビルドにSDK8.1を使用しているが、Microsoft Visual Studio 2019ではSDK8.1はインストールできないため、古いVisual Studioをインストールする。

### 手順２－１
~~~
Download the current taglib release and extract it somewhere on your computer.
~~~
TagLibをダウンロードして解凍しておく。
(https://taglib.org/#windows)

### 手順２－２
~~~
Start the VS2015 x64 Native Tools Command Prompt. On Windows 8/10, it might not appear in your start menu, but you can find it here: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio 2015\Visual Studio Tools\Windows Desktop Command Prompts
~~~
スタートメニューから「VS2015 x64 Native Tools Command Prompt」を実行する。
★コマンドプロンプトは複数あるため、間違えないように！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10294/10014de8-2136-e5e2-f56c-13e7ae04f619.png)

### 手順２－３
~~~
3. Navigate to the extracted taglib folder and type: cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=".\taglib-install" to generate the Visual Studio project files.
~~~
taglibの解凍先に移動して、以下コマンドを実行(※)
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=".\taglib-install"

taglibフォルダ内に「taglib-install」のフォルダができて、ライブラリが作成される。

※ cmakeコマンドが実行できなかったため、CMAKE（cmake-3.16.4-win64-x64.msi）をインストールした。
[CMAKE](https://cmake.org/download/)

### 手順３
~~~
3. Still in the VS2015 command prompt, navigate to the pytaglib directory.
~~~
手順２のコマンドプロンプト上でpytaglibのディレクトリへ移動する。

### 手順４
~~~
4. Tell pytaglib where to find taglib: set TAGLIB_HOME=C:\Path\To\taglib-install
~~~
手順２で作成したC++のTagLibのパスを通しておく。

### 手順５
~~~
5. Build pytaglib: python setup.py build and install: python setup.py install
~~~
以下コマンドを実行してpythonで利用可能にする。

```sh
python setup.py build
python setup.py install
```
★ 間違えて別のコマンドプロンプトで実行すると、「fatal error LNK1112」で怒られる。ここで1日はまった・・・

### 最後に
これでようやくサンプルにあるような感じでタグ情報の取得ができた！
flacもwaveも同じコードで取得できるため、個人的にはmutagenよりもいいかなと感じました。
しかし、TagLibのC++ライブラリのビルドから作業が必要であり、日本語の情報が少なく準備が大変です。

```sample.py
import taglib
song = taglib.File("/path/to/my/file.wave")
print(song.tags)
```

## 参考
- [mutagenリンク：pip install mutagenで使用可能。waveにこだわらないならこちらで十分](https://github.com/quodlibet/mutagen)
laravel migration カラム名変更（初心者向け）

phpについての初投稿になります！

リファレンスにも書いてありますが、つい忘れてしまうのでメモ程度に紹介します

laravel 6.x系です
osはmacです

# カラム名を変更、削除するには

(※この記事を書いた当時のコマンドです。すぐ下の追記の記事を合わせて読んで参考にしてください。)
ターミナルで

```
$ composer require doctrine/dbal
```

↑のコマンドを叩き、composerで"doctrine/dbal"

をインストールしましょう！（リファレンスに書いてあるので臆せずインストールしましょう！）

laravelはデフォルトではカラム名の変更や削除はできません！（なんでやねん！まぁなんか理由があるのでしょう）

※ 2021/07/06追記: 現在上記のコマンドでインストールしてmigrateを実行すると

```
Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
```
多分こんなエラーになります。※確かlaravel 8.xでもなった気がする
最新のバージョンがインストールされるとエラーとなってしまうので、

```
composer require "doctrine/dbal:2.*"
```

と2系をインストールするとうまくいきます。いくはず。いかなかったら気合いが足りないと思うので、今隣にいる誰かに腹パンしてもらってから再度実行してみてください。
(参考: [Laravelのmigrateで「doctrine/dbal」をインストールしても「Class ‘Doctrine\DBAL\Driver\PDOMySql\Driver’ not found」が発生](https://doroidpanic.com/laravel%E3%81%AEmigrate%E3%81%A7%E3%80%8Cdoctrine-dbal%E3%80%8D%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%81%A6%E3%82%82%E3%80%8Cclass-doctrinedbaldriverpdomys/))

で、ターミナルで

```
$ php artisan make:migration rename_変更前のカラム名_to_変更後のカラム名_on_テーブル名_table --table=テーブル名
```
とコマンドを叩きます(オプションの"--table=テーブル名"により、migtarionファイル作成時にテーブル名が追加され作成されます。また、migrationファイルの名前は正直適当でいいと思いますが、ファイル名をみて何の内容のmigrationファイルが実行されたかわかりやすい名前をつけた方が後々楽になると思います。)

```〇〇_rename_変更前のカラム名_to_変更後のカラム名_on_テーブル名_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class RenameNightSpandingToNightSpendingOnCostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('costs', function (Blueprint $table) {
            $table->renameColumn('night_spanding', 'night_spending');//<-記述
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('costs', function (Blueprint $table) {
            $table->renameColumn('night_spending', 'night_spanding');//<-記述
        });
    }
}

```

こんな感じでマイグレーションファイルを作成します

upは

```
$ php artisan migrate
```
↑で実行される内容

downは

```
$ php artisan migrate:rollback
```

↑などで実行される内容を記述します
なので、カラム名の変更や、型の変更などは、基本的にはupで書いた内容の逆を記述すればいいと思います。
（php artisan migrate:refreshなども全てロールバックしてmigrateし直すコマンドなどあるので、downはちゃんと書いておかないとエラーの原因になります！）

で、

```
$ php artisan migrate
```

でカラム名を変更することができます！

カラム削除する場合でも、"doctrine/dbal"のインストールが必要みたいですので、個人的にはlaravelプロジェクトを立ち上げたらすぐにインストールしておいた方がいいのかな？と感じてます。