OmniAICreator/Qiita-1.07M huggingface dataset:
domをいじってclassを付加（モーダルの出現中にページスクロールをさせない、一定の高さスクロールしたらtableのheaderを固定する等）


```javascript

document.getElementById('hogeID').classList.add('fix')

document.getElementById('hogeID').classList.remove('fix')

document.body.classList.remove('no-scroll')

document.getElementsByClassName('test')[0]

```

例：一定の高さスクロールしたらtableのheaderを固定する

```javascript
/**
 * tableのheaderを固定処理
 */
onScroll(e) {
  const fixTableTop = document.getElementById('fugaID').getBoundingClientRect().top

  if (fixTableTop < 140) {
    document.getElementById('tableHeader').classList.add('fix')
  } else {
    document.getElementById('tableHeader').classList.remove('fix')
  }
},
```

##参考

####Document.getElementsByClassName()
https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName

####Element.getBoundingClientRect()
https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect

####モーダルを開いている時にページがスクロールしてしまうのを防ぐCSSとJavaScriptのテクニック
https://coliss.com/articles/build-websites/operation/javascript/prevent-page-scrolling-when-a-modal-is-open.html
ZONe 'mad_hacker'; にデザインされたプログラムを実行してみた

#はじめに

先日、みんな大好きエナジードリンクのZONeより、**'mad_hacker'; Ver1.0.0**が発売されました。
何というネーミングでしょうか。マッドハッカー...
早速買ってみたところ、何やら缶にプログラムがデザインされていました。

![代替テキスト](https://mh-procon.zone-energy.jp/assets/images/pc/product_info/product.png)

かっこいい！！これは実行してみたい...！

#コード入力
何はともあれ、まずは写経です。
だまってコードを打ち込みます。

缶という円柱に描かれただけでも読みにくいのに、改行もない、他のデザインにコードが邪魔されてる、文字色も見えにくいですが、**とにかくカッコいい**ので頑張って読み取ります。

全部で缶に30行ほどのコードがありますが、4行半ばまででひとつの関数が終わってるぽいので、今回はそこまで。

何やら**Javascript** という言語らしいです。
経験がない言語ですが、何となく改行しながら書きます。


```javascript:mad_hacker.js
 function binarySearch(arr, val, min, max){
     if (max < min) {
         return false;
     }
     const half = Math.floor(min + (max - min) / 2);
     if(arr[half] === val){
         return half;
     }
     return arr[half] > val ? binarySearch(arr, val, min, half - 1) : binarySearch(arr, val, half + 1, max);
 }
```



# binarySearch（二分探索）
関数名から察するに、これは[二分探索](https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2)アルゴリズムです。
ソート済の配列やリストの中から、特定の値を見つけるアルゴリズムですね。
Wikipedia様の例を参考に、値を入れてみます。

>下記のような配列から25を探しだすことを考える。

| 位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|データ | 1 | 3 | 5 | 11 | 12 | 13 | 17 | 22 | **25** | 28|

```javascript:main.js
// 配列作成
search_list = [1,3,5,11,12,13,17,22,25,28]

// 関数実行
ans = binarySearch(search_list, 25, 0, search_list.length);

// 結果確認
console.log(ans); 
```
第一引数に探索対象配列の`search_list`を、第二引数に探索対象である`25`を渡します。
第三、第四引数の`min`と`max`は探索対象の数値ではなく、配列の要素数を渡してあげるようです。
`min`には`0`、`max`には`search_list.length`で取得した配列の要素数（=10）を渡します。

# 実行結果

Javascript は未経験で環境もないため、今回は[paiza.io](https://paiza.io/projects/nFPkbweawnDHU4Fb_yqIxw?language=javascript)でJavascript を実行しました。

```console:実行結果
8
```
ここでもう一度例題を見てみましょう。

>下記のような配列から25を探しだすことを考える。

| 位置 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|データ | 1 | 3 | 5 | 11 | 12 | 13 | 17 | 22 | **25** | 28|

この`25`という数字が配列のどの位置にあるか探索するのが二分探索でした。
位置としては`9`番目ですが、配列は0始まりなので、`8`で正解ですね！



#まとめ
**グレープソーダのようで美味しかったです。**

ZONe 'mad_hacker';　には**ソートされた配列から任意の値を取り出す二分探索がコーディング**されていました。
ハッカー関係あるのでしょうか？

しかし何にせよ、Javascript 未経験だったので良い勉強になりました。


残りの30行もどうやら探索アルゴリズム系っぽいです。気になりますね。
[AtCoderと連携している](https://mh-procon.zone-energy.jp/)みたいです。
続きは気が向いたら。
Postmanを使ったAPIへのリクエストの投げ方。

#はじめに
API開発時に、リクエストを投げてどのような値が返ってくるか確かめたいときに、CUIで操作するのは何かと不便です。そこで、ここではPostmanを使う方法を紹介します。

#準備
https://www.postman.com/

Postmanのページから自身の環境にあったverをダウンロードします。
インストラクションに従ってインストールを行ってください。

#Posatmanに使うAPIの作成
Postmanでリクエストを投げた先のAPIを作成します。
ここでは例として簡単なAPIを用います。

```
@app.route('/test',methods=["POST"])
def test():
    data=request.get_json()
    response = {
        "test": data
    }
    return jsonify(response)
```

#Postmanを用いたリクエスト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1400939/9cd193cb-086c-8ca1-f9d4-7f3fe9e6cb25.png)

Postmanを起動すると、餓えのような画面が出てきますので、Postを選択し、URLを入力します。
Vitis HLS と Vivado で作った回路を PYNQ を使って FPGA 上で動かすまで ー④PYNQ を使って実機で動かすー

諸事情あり，このページは以下のページに移行しました．
ご愛読ありがとうございます．

https://blog.n-hassy.info/2021/05/vitis-hls-to-fpga-4/
[Rails] devise導入方法

## はじめに
自作のRailsアプリケーションでdeviseを使用したので備忘録として残しておきます。

## deviseとは
railsのgemの一つでログイン認証機能を簡単に実装することができる。

## インストール
`Gemfile`に以下のように記述してください

```
gem 'devise'
```
ターミナルで以下コマンドを実行します。

```
$ bundle install
$ rails g devise:install
```
以上でインストールは終わりです

## ビューファイルの作成
以下のコマンドでdeviseの認証周りが実装されたビューファイルが作成されます。

```
$ rails g devise:views
```
見た目はかなり簡素になっているのでビューファイルを編集する必要があります。

## Userモデルの作り方
deviseをインストールをすると認証が使えるモデルを作成することができます。
`rails g model user`ではなく以下のコマンドを使います。

```
$ rails g devise user
```
このコマンドを実行すればログイン認証ができるファイルが自動で作成されます。
同時に`routes.rb`に`devise_for :users`が追記されサインアップやログイン、ログアウトのルーティングが自動で作成されます。
マイグレーションファイルは以下になっています。
最初はnameカラムがないので入れておきましょう。

```

class DeviseCreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.inet     :current_sign_in_ip
      t.inet     :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      t.string   :unlock_token # Only if unlock strategy is :email or :both
      t.datetime :locked_at

      t.string :name                  　#ここにnameを追加
      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

```

またマイグレーションファイルを追記した場合は`user`カラムを受け入れてくれるように`application_controller.rb`に以下の記述をしておきましょう

```
# 以下を追加
before_action :configure_permitted_parameters, if: :devise_controller?

def configure_permitted_parameters
        # サインアップ時にusernameのストロングパラメータを追加
        devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :image])
        # アカウント編集の時にnameとprofileのストロングパラメータを追加
        devise_parameter_sanitizer.permit(:account_update, keys: [:username,:image,:profile])
end
```
Arduino UNOをPCのDigital I/Oとして活用する

![Arduino_Firmate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506495/e5a37882-6b40-9bd3-252c-42972adc6cf5.png)
Windows PCには単純なInput/Output ADなどが使うことができません。
過去にWindows PCにはプリンタポートやシリアルポートなど組み込み用途と使える
インターフェースがありましたが、最近のPCはそれら古いインターフェスは省略されています。

Arduino UNOはスケッチを使って簡単に組み込みプログラムを動作できるのですが
組み込みプログラムをある程度知識が必要です。

ArduinoにはPCと接続を意識したFimata というFWが準備されています。
これを使えばPythonプログラミングでI/O操作を行うべく使えるようになります。
サポートされているI/Oインターフェスを記載します。

現在、ArduinoのFirmataに接続するPythonインターフェースは大きく分けて2つあるようです。

pyFirmata

|I/O Pin|ADC Input|PWM output|I2C|SPI|UART|
|:--:|:--:|:--:|:--:|:--:|:--:|
|〇|〇|〇|×|×|×|

pyMata

|I/O Pin|ADC Input|PWM output|I2C|SPI|UART|
|:--:|:--:|:--:|:--:|:--:|:--:|
|〇|〇|〇|〇|×|×|

UARTはFirmataの制御用で使えないので仕方ないですが
SPIが対応していないのが惜しいところ。pyMataであればI2C対応しているので
センサー機器をつないで制御するには向いています。
簡単に使うのであればpyFimataの方が使いやすいかもしれません。
【XAMPP】 phpmyadmin サーバー上でいくつかのエラーが検出されました 対処法

XAMPPでphpmyadminを起動させデータベースを選択すると、
いきなり「phpmyadmin サーバー上でいくつかのエラーが検出されました」という警告が出てきたので、
対処法をメモ。

原因を一つ一つつぶして行っても良いかと思いますが、
触っていないファイルのエラー数が多かったので、
原因はphpmyadminのバージョンが古いのではと推測。

phpmyadminのサイトを調べてみると、
確かにphpmyadminのバージョンと対応するPHPバージョンが合っていないと判明。

▼phpmyadmin EWBサイト
https://www.phpmyadmin.net/downloads/

XAMPP/phpMyAdmin ファイルを、XAMPP/phpMyAdmin.oldなどと名前を変更し、
新しいバージョンのファイルを上記サイトからダウンロードし、phpMyAdminに名前を変更後
XAMPPディレクトリ配下に入れる。
(もともとphpMyAdminがあった場所と同じところ)

```
(例えばphp7.1なら)
phpMyAdmin-5.1.0-all-languages.zip　⇒　XAMPP/phpMyAdmin
```

phpMyAdmin.oldからconfig.inc.phpをコピーし、
phpMyAdminに入れなおす。

```
XAMPP/phpMyAdmin/config.inc.php(入れる)
```

MySQLを再起動させると、エラー解消。
GitHubでセキュリティの脆弱性を自動で修正する

## はじめに

ある日、GitHubから*Your repository has dependencies with security vulnerabilities*とメールが来て、確認するとこのような警告がされていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/7c4747d5-9a8f-e41c-d0fd-644cf01656d6.png)

脆弱性があるとのことで`See security alerts`を押すと、詳細な内容を確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/83f7fc58-6360-2c1a-513d-0b3c9f5a0ae7.png)

## 原因

原因は利用していたライブラリ[System.Text.Encodings.Web](https://www.nuget.org/packages/System.Text.Encodings.Web)のバージョン5.0.0に脆弱性があるとのことで最新版にバージョンアップすれば解決するそうです。

## 自動で解決

詳細を見ていると`Create automated security fix`と自動で修正してくれるようなボタンが出てきます。（混み具合にもよるそうでちょっと時間がかかるみたいです）
※自動アップデートを有効にしていれば勝手にプルリクエストが作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/f2fe517b-045d-3bdc-e1a9-3a4ce6a5fae0.png)

すると下記のようなプルリクエストが作成されますので、これをマージするだけで脆弱性の警告を解消できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/1697444e-a27f-df85-d260-75d5efcf9338.png)

## Dependabot Alertsとは

今回、脆弱性の通知から自動修正まで行ってくれた機能について調べてみるとDependabotの機能だそうで以下の記事がわかりやすかったです。

参考：

https://zenn.dev/yuuhu04/articles/about-github-alert

## まとめ

- Dependabotを利用して、自動で脆弱性の検出から修正を行ってみた。
- ライブラリのバージョン更新を日々チェックするのは大変ですし、変更内容がプロジェクトに影響するのか確認するのもなかなか難しいので、このようなサービスは有効に活用していきたいですね。
Nginx　pidとは何か

# pidとは何か

Process IDの略。
psコマンドで見ることができるプロセスに割り当てられる整数の通し番号こと。

pidファイルはメインプロセスのプロセスIDが書き込まれるファイルを示す。

[プロセスID（PID）とは - IT用語辞典 e-Words](https://e-words.jp/w/%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9ID.html)

## Nginxにおけるpidディレクティブ

メインプロセスのプロセスIDが書き込まれるpidファイルを示すディレクティブ。
コンパイル時のデフォルトの値を上書きします。

```nginx.conf
pid /var/run/nginx.pid
```

pidファイルにはマスタプロセスのPIDが出力されます。pidディレクティブを指定しなかった場合、コンパイル時に指定したファイルパスが使用されますが、サーバの起動スクリプトやプロセス管理ツールに合わせ、適切なファイルパスを指定しましょう。

コンパイル時に指定しなかった場合、デフォルト値は`logs/nginx.pid`です。

Nginxのグローバル設定の1つです。
グローバル設定はpid以外にも主要なものとして以下が存在します。

- user
- worker_processes
- error_log
- pid
- use
- worker_connections


## pid関係のエラー

pidディレクティブの書換えなどで、pidに関するエラーが出ることがあります。

```
nginx: [error] invalid PID number "" in "/run/nginx.pid" alpine
```

findコマンド等を使用して、pidが生成されている場所を調べて、configファイルを見直すか、
nginxのプロセスを全部切った上で再起動させると治ることがあるようです。

[linux - ERROR : invalid PID number "" in "/run/nginx.pid" - Stack Overflow](https://stackoverflow.com/questions/36176255/error-invalid-pid-number-in-run-nginx-pid)
同一の GPU の一方を PCI パススルーする

Arch Linux での方法が [OVMF による PCI パススルー](https://wiki.archlinux.jp/index.php/OVMF_%E3%81%AB%E3%82%88%E3%82%8B_PCI_%E3%83%91%E3%82%B9%E3%82%B9%E3%83%AB%E3%83%BC) にあるので、これを参考に Ubuntu 16.04.7 LTS でも実施した。

## 編集したファイル

```conf:/etc/modprobe.d/vfio.conf
install vfio-pci /usr/bin/vfio-pci-override.sh
blacklist nouveau
blacklist snd_hda_intel
```

下2行は不要なドライバーを抑止するためなので、不要かも。

```sh:/usr/bin/vfio-pci-override.sh
#!/bin/sh

for i in /sys/bus/pci/devices/*/boot_vga; do
  if [ $(cat "$i") -eq 0 ]; then
    GPU="${i%/boot_vga}"
    AUDIO="$(echo "$GPU" | sed -e "s/0$/1/")"
    echo "vfio-pci" > "$GPU/driver_override"
    if [ -d "$AUDIO" ]; then
      echo "vfio-pci" > "$AUDIO/driver_override"
    fi
  fi
done

# equivalent for "options vfio-pci ids=8086:8d20" in /etc/modprobe.d/vfio.conf
for i in /sys/bus/pci/devices/*; do
  if [ $(cat "$i/vendor") = "0x8086" ]; then
    if [ $(cat "$i/device") = "0x8d20" ]; then
      echo "vfio-pci" > "$i/driver_override"
    fi
  fi
done

modprobe -i vfio-pci
```

前半は前記ページの通りで、後半は GPU とは別にパススルーするマイク＆ヘッドホン端子向けの設定。
modprobe の設定における`options` との共用に確信がなかっただけなので、もっとスムーズなやり方があるかもしれない。
ただ、このファイルを `/usr/bin` に置くのはなんか違う気がする。

```conf:/etc/initramfs-tools/modules
vfio_pci
vfio
vfio_iommu_type1
vfio_virqfd
```

前記ページの通り。

```sh:/usr/share/initramfs-tools/hooks/vfio-pci-override
#!/bin/sh

PREREQ=""

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

. /usr/share/initramfs-tools/hook-functions
copy_exec /usr/bin/vfio-pci-override.sh
```

作成したファイルを initramfs の中から利用するための設定。テンプレート通り。

## その後の手順

1. `update-initramfs -u` で `/boot/initrd.img-xxx` （xxx はカーネルのバージョンなど）を更新する。
1. `lsinitramfs` で、必要なファイルが追加されていることを確認する。
1. シャットダウンし、ディスプレイの端子を接続して起動する。
1. 一方の GPU が boot_vga になり、そちらに Ubuntu のログイン画面が表示されるので、ログインする。
1. `dmesg | grep -i vfio` や `lspci -nnk` で他方がパススルーされていることを確認し、ゲストにパススルーしたデバイスを追加する（前記ページの通り）。
プロセスビルダーとフローの違いと対応

#はじめに
ここ1年のアップデートで、フローの使い勝手は大きく向上しました。
フローのバリエーションが増え、トリガの種類が増え、利用可能なリソースが増え、スケジュール済みパスが増え…
出来ることの幅も大きく広がりました。~~（むしろできないことが探すのが難しいぐらい）~~

処理の速度もプロセスビルダーと比べて格段に速く（保存前トリガでは10倍速いと謳われている）、これからはプロセスの自動化はフローを主軸に考えることになると思います。
Salesforce側もこれからはフローを中心にしていこうと考えているような気もします。（ここ最近、プロセスビルダーにアップデートがかかっていないはずですし。）

しかし、プロセスビルダーとフローは全く同じ感覚で使用できるものではありません。「プロセスビルダーの方が直感的に使えてやりやすい」というような声も結構耳にします。

ただ、プロセスとフローが処理される順番が決まっており、両者が混在していると思わぬ悪影響が発生する懸念があります。どちらか1つに統一したほうが、将来的に良いような気もします。

ということで、今回は両者の大きな違いを3点ほど上げていこうかな、と思います。
#違い①:項目に割り当てる値に数式を直接使用できない
プロセスビルダーでは項目を更新する際に、値に数式を入力することが可能です。
フローにおいて、項目に値を割り当てる際は「割り当て」要素を使用することになります。ですが、この要素の中で割り当て値に直接数式を入力することはできません。（入力したらエラーを吐かれます。）

でもご安心。

フローでは、変数・定数などといった「リソース」を自分で用意することができます。~~（この「リソース」がフローの理解を難しくしているような気もする）~~
リソースを新規作成するときの形式を「数式」にして、数式を入力し、そのリソースを「割り当て」要素の割り当て値に使用することで解決できます。

#違い②:フローで使用できない関数がある
自動化において、「レコードの更新前の値を参照したい」とか、「レコードのこの項目が更新されたか調べたい」とか、「このレコードが新規に作成されたものか調べたい」といった状況に遭うことがあります。
この場合、プロセスビルダーでは、PRIORVALUE()・ISCHANGED()・ISNEW()といった関数を使用することで容易に実現することが可能です。
フローでは、これらの関数を使用できず、別の方法でこのロジックを実現することも、つい最近までできませんでした（多分）。
このことが、自動化ツールとしてプロセスビルダーを使用する要因となっていました。

そう、つい最近までは。

Spring'21のアップデートのリリースノートにこんな記述がありました。
>__フローをトリガしたレコードの前の値の参照__
>レコードが更新されたときに、そのレコードの前の値に Salesforce Flow でアクセスできるようになりました。$Record__Prior グローバル変数には、フローの実行直前のレコードの値が含まれます。

__これを待っていたんだよこれを！__と叫びたくなるようなアップデートでした。
今後はこの機能を利用することで、PRIORVALUE()・ISCHANGED()・ISNEW()といったフローで使用できない関数の完全代替が可能となりました。

具体的には、
PRIORVALUE():\$Record\__Priorに直接アクセスする
ISCHANGED():数式リソースや「決定」要素で、\$Record\__Priorと\$Recordを比較する
ISNEW():数式リソースや「決定」要素で、\$Record\__PriorがNullかどうか判定する

こうすることで、代替が可能です。プロセスビルダーを利用する理由が1つ消えました。

#違い③:スケジュール済みタスクの考え方
時々、「条件を満たしてもすぐに処理を行わず、一定時間後に処理をしてほしい」といった状況に遭うことがあります。
この場合、プロセスビルダーでは条件を設定したのちに「スケジュール済みタスク」を設定することで実現できました。
フローには、つい最近までこのような機能がありませんでした。
このことが、自動化ツールとしてプロセスビルダーを使用する要因となっていました。

ええ、つい最近までは。

Spring'21のアップデートのリリースノートにこんな記述がありました。
>__トリガイベントの後にレコードトリガフローの一部を実行__
>トリガイベントの発生後、動的にスケジュールされた時間にフローの一部を実行する場合は、スケジュール済みパスをレコードトリガフローに追加します。スケジュール時間は、レコードの作成時や更新時、またはレコード内の項目値に基づくことができます。

__これを待っていたんだよこれを！__と叫びたくなるようなアップデートでした（二回目）。
この機能を使うことで、プロセスビルダーでの「スケジュール済みタスク」と同じようなことができるようになりました。プロセスビルダーを利用する理由がまた1つ消えました。

ですが、この二つには__大きな考え方の違い__が存在しています。

プロセスビルダーでは、「条件を満たしたら、タスクをスケジュールする」といった形です。
フローでは、「スケジュールされた時間になったら、パス（「決定」要素などの条件分岐も含む）を実行する」

といった感じです。条件分岐とスケジュールの順番が逆になっているような感じですね。
そのため、フローではスケジュールによってパスを複数用意することになります。
【Docker】コマンド一発でWebコンテンツが格納されたフォルダをhttp://localhost/でテストする。

Dockerを用い、公式のnginxコンテナでやります。
何番煎じか分かりませんが、シンプルな記事が少なかったのでメモとして。

## 条件
Dockerが使える環境

- コンテナ名(任意)：nginx-container
- Webコンテンツが格納されたフォルダ：/home/username/public_html
- ポート番号：8080

テスト用に、/home/username/public_htmlに次のファイルを置いておく

```html:index.html
<html>
<body>
index
</body>
</html>
```

## コマンド

```shell
docker run \
    --name nginx-container \
    -v /home/username/public_html:/usr/share/nginx/html:ro \
    -p 8080:80 \
    -d \
    nginx:latest
```

## 結果

http://localhost:8080/
へアクセスし「index」と表示されれば成功です。
nkfコマンドでファイルの文字コードと改行コードを統一する

nkfは「Network Kanji Filter」の略であり、文字コードと改行コードを変換するコマンドです。
異なるOS(WindowsやLinux)でファイルを共有するときの問題を解決します。

今回はLinux上でnkfコマンドを利用して、文字コードと改行コード以下に統一します。

- 文字コード: UTF-8(BOMなし)
- 改行コード: LF(Unix系)

## nkfコマンドのインストール

以下のコマンドでnkfをインストールできます。

```bash
# CentOS7
sudo yum install -y nkf

# CentOS8
sudo dnf install -y --enablerepo=PowerTools nkf

# ubuntu
sudo apt install -y nkf
```

## ファイル変換

以下のテキストファイルを変換します。

```test.txt
test
```

あえて、文字コードはUTF-8(BOMあり)で改行コードはCRLF(Windows系)にしてあります。

`cat -e test.txt`で確認すると、BOMが入っていることと改行コードがCRLFになっていることを確認できます。

```bash
$ cat -e test.txt
M-oM-;M-?test^M$
```

`M-oM-;M-?`はBOMであり、`^M$`は改行コードのCRLFです。(`^M`がCR、`$`がLF)

### 文字コードの変換

まずは文字コードをUTF-8(BOMなし)に変換します。`-w`オプションで変換ができます。

```bash
$ nkf -w test.txt
test^M$
```

### 改行コードの変換

次に改行コードをLFに変換します。`-d`オプションで変換できます。

```bash
$ nkf -d test.txt
M-oM-;M-?test$
```

## まとめ

もちろんオプションを併用することもできるので、一括で変換する場合は以下になります。

`--overwrite`オプションを指定すると、指定ファイルが上書きされます。
オプションがない(デフォルト)だと標準出力に結果が出力されます。

```bash
$ nkf -wd --overwrite test.txt
$ cat -e test.txt
test$
```

## Reference

- [UTF-8のhttpd.confでエラー - think-t の晴耕雨読](https://think-t.hatenablog.com/entry/20100713/1279034152)
- [【 nkf 】コマンド――文字コードと改行コードを変換する：Linux基本コマンドTips（51） - ＠IT](https://www.atmarkit.co.jp/ait/articles/1609/29/news016.html)
【メモ】Gemfile.lockをGitの追跡から除外したい


Gemfile.lock について、マージすると本番環境にまで反映されちゃうので、
いつか入れるとしても今はコミットに含めない。
(入れるなら入れるで別で専用のマジリクを作るはず！)

との事で、Gemfile.lockをGitの追跡から除外します。

通常であれば.gitignoreに記載するいう対応ですが、
今回は一度コミットしてしまったため、後から追跡を除外します。

```
ローカルの追跡から除外
$ git update-index --skip-worktree Gemfile.lock

設定の確認
$ git ls-files -v
```

▼設定の見方はこちらで確認

参照元：
https://qiita.com/usamik26/items/56d0d3ba7a1300625f92
【ひらがな⇔カタカナ】あいまい検索にヒットしたテキストを一括置換する方法【大文字⇔小文字】

# あらすじ
下記のような処理をつくる必要がありました。
1. ひらがな・カタカナどちらでもヒットする曖昧検索をおこなう
2. ヒットしたテキストを、正規表現を使って置換する

（ちなみに具体的には、長文の中からユーザーが入力した検索ワードをあいまい検索し、ヒットした箇所を`<span>`で囲んだ状態の文字列に変換し、強調表示させる、というタスクでした。）

さてどうやって実装したもんか、と参考記事をググってみましたが、
ドンピシャな記事はなかなか出てきませんでした。

そのかわり「正規表現であいまい検索をする方法」みたいな記事はいくつかでてきました。
それは「検索対象と検索ワードをそれぞれひらがな(orカタカナ)に変換して、正規チェックする」という内容でした。
（
　つまり検索対象が`私の名前はゴンザレスたろうです`という文で、
　検索ワードが`ゴンザレスタロウ`だった場合、
　検索対象を`私の名前はごんざれすたろうです`に変換、
　検索ワードも`ごんざれすたろう`に変換した上で
　正規表現で検索する、という方法です。
）

素直さがウリである（？）わたしは、言われたとおりにコードを書いてみたのですが、
このような方法だと、ヒットしたテキストを正規置換に利用しようとしたとき、結構複雑な処理が必要でした。

なぜなら、
ヒットしたテキストは、すでにひらがなに変換されているものなので、
ひらがな・カタカナ表記をそのままの状態で置換をしたい場合、
文章の何文字目から何文字目がヒットしていたのかを判定し、
元々の文章から該当する箇所の表記をひっぱってくる必要がありました。
しかも、JavaScriptには、正規マッチした文字列をすべて一気に置換してくれるような関数や、
マッチしている箇所のインデックス番号を取得するような関数が存在しないので、
ヒットしたテキストを１つ１つ置換しつつ、
置換後の文字列と置換前の文字列のインデックスのズレも考慮して置換をしていく必要があったのです。
（
　たとえば正規置換で、`私の名前はゴンザレスたろうです`を
　`私の名前は<span>ゴンザレスたろう</span>です`に変換したい場合、
　置換によって追加される13文字のインデックスのズレを加味したうえで
　ひきつづき置換処理を続ける必要がありました。
　（ヒットする箇所が１箇所だけではない可能性があるので。）
）

絶望に暮れ、悠久とも思える１０分もの間悩んでいたわたしに、
発想の女神の祝福が舞い降りました。
検索対象を置換するんじゃなくて、そもそも正規表現をひらがなでもカタカナでもヒットする形にすれば、とってもシンプルになる！
そのことに気づいたわたしは、早速コードを書きはじめました・・・。

# コード
```JavaScript
function katakanaToHiragana(src) {
    return src.replace(/[\u30a1-\u30f6]/g, function(match) {
        const chr = match.charCodeAt(0) - 0x60;
        return String.fromCharCode(chr);
    });
}

function hiraganaToKatagana(src) {
    return src.replace(/[\u3041-\u3096]/g, function(match) {
        const chr = match.charCodeAt(0) + 0x60;
        return String.fromCharCode(chr);
    });
}

function escapeRegExp(string) {
    return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
}

function generateFuzzyRegExp(searchWord) {
    searchWord = escapeRegExp(searchWord);
    const chars = searchWord.split('').map(char=>{
        const hiragana = this.katakanaToHiragana( char );
        const katakana = this.hiraganaToKatagana( char );
        if( hiragana===katakana ) return char;
        return `(${hiragana}|${katakana})`;
    });
    const fuzzyRegExp = new RegExp( `(${chars.join('')})`, 'ig' );
    return fuzzyRegExp;
}
```

# 説明
`katakanaToHiragana` `hiraganaToKatakana`
カタカナをひらがなに、ひらがなをカタカナに変換する関数です。
[こちらのリポジトリ](https://gist.github.com/kawanet/5553478)を参考にさせていただきました。

`escapeRegexp`
正規表現と認識されてしまう文字をエスケープする関数です。
[こちらの記事](https://qumeru.com/magazine/108)を参考にさせていただきました。

`generateFuzzyRegExp`
引数に渡された文字列から、
カタカナ・ひらがな・大文字・小文字を区別しない正規表現を生成する関数です。

エスケープ後の文字列を１文字ずつ分割し、
`(あ|ア)`のようなパターンに変換して配列に格納しています。
joinで１つの文字列にまとめたら、
まとめて $1 で拾えるようにカッコで囲ってあげて、
正規表現に変換してあげれば完成です！

（正規表現のiオプションによって、英大文字・英小文字は自動的に区別しない仕様となります。）


# 感想
技術レベル的にはたいしたことないですが、
発想の転換って大事だな〜と思いました。
VSCodeでC++プログラムのデバッグを行う

# 概要

vagrant 環境で開発した C++プログラムを VSCode で検証する際に、GDB を使おうと思い、試行錯誤した内容を備忘録として残します。

# 環境

- VSCode 1.55.2
- vagrant + VirtualBox (CentOS)

# C++プログラムの設定

プログラムを make する際に、デバッグモードにしておく必要があるようです。

# VSCode の設定

VSCode で GDB を実行するためには、`.vscode`ディレクトリ直下にある`launch.json`ファイルを設定する必要があります。

```json:launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "g++ デバッグ",
      "type": "cppdbg",
      "request": "launch",
      "program": "/home/vagrant/(実行ファイルまでパス)/(実行ファイル名)",
      "args": ["aaa.txt", "bbb.log", "ccc.p" "-d"],
      "stopAtEntry": false,
      "cwd": "/home/vagrant/(データのあるパス)",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "setupCommands": [
        {
          "description": "gdbの再フォーマットを有効にする",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",
      "miDebuggerPath": "/usr/bin/gdb"
    }
  ]
}
```

下記のうち、設定が必要な項目は下記の４つです。

- name : 実行するデバッグの名称。なんでも良い
- program : 実行ファイルを指定（絶対パスで指定しました）
- args : プログラム実行の際に必要な引数を指定（必要なファイル名、オプション名を""で囲んで一つずつ指定する)
- cwd : プログラム実行に必要なファイルのディレクトリを指定

`stopAtEntry`を true にすれば、デバッグ開始後、処理の冒頭で自動でブレイクします。

### 注意点

上記設定後にデバッガーを実行したところ、エラーが発生しました。
色々と原因を調べてみたところ、`launch.json`ファイルの下記記述が悪さをしていたようです。
`"preLaunchTask": "C/C++: g++ アクティブなファイルのビルド",`
本記述は、`task.json`ファイルの設定で事前にビルドをしてくれるようですが、私の環境ではこの事前ビルドでエラーが発生したため、本記述を削除したところ正常にデバッガーを起動できました。

# GDB 実行方法

launch.json ファイル設定後、下記手順を実行すれば、デバッガが起動できました。

1. VSCode を再起動する(launch.json の変更を反映するため）
2. VSCode 画面左側の「実行とデバッグ」ボタン(虫のマーク）をクリックする
3. 画面左上の「実行とデバッグ」のプルダウンから、name で指定したデバッガを選択する
4. プルダウンのすぐ左の再生ボタンをクリックする
sedやawkと踊(ダンス)っちまった時に見るページ

でえじょうだ、どうせみんな大して使いこなせねえ。

# sed

## `sed -n 😀p` 

- 😀行目のみを出力する
  - 最初の行の行番号は1

| 例 | 意味 |
| ---- | ---- |
| `sed -n 2p` | 2行目を出力する |


## `sed -e 's/😀/😍/g'`

- 「パターン😀」を「文字列😍」に置換する
- パターンは正規表現も使えるみたい
- `/` の区切りは、 `#` などの他の記号も使える
 
| 例 | 意味 |
| ---- | ---- |
| `sed -e 's/xxx/yyy/g'` | `xxx` を `yyy` に置換する |
| `sed -e 's#/#:#g'` | `/` を `:` に置換する |

# awk

## `awk -F'😀' '{ print $😍 }'` 

- 行を😀で分割して、😍列目を出力する
- `-F` を省略するとスペースで分割する

| 例 | 意味 |
| ---- | ---- |
| `awk -F',' '{ print $2 }'` | `,`で分割して、2列目を出力 |
| `awk '{ print $3 }'` | スペースで分割して、3列目を出力 |
【AWS】IAMユーザーのセキュリティを設定 no.3

![AWS (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/fdcbf346-adc8-7298-4445-9d67601ac181.png)


こんにちは。まゆみです。

AWSについての記事をシリーズで書いています。

今回は第3回目になります。

[前回の記事](https://qiita.com/Mayumi_Pythonista/items/c856437a2ab47779ed69)では、IAMを使って、ユーザーを追加する方法を書きました。

今回は、<font color="Red">ルートユーザーやIAMユーザーのセキュリティを強化する方法</font>について書いていきます。

ではさっそく始めていきますね。

#ルートユーザーとIAMユーザーは二重に守られる

![見出しを追加 - 2021-04-28T161342.534.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/019adcee-929e-c5f5-4ddd-8fbb0e32bd07.png)

AWSのユーザーは、二重のレイア―を作ることで守られます。

>①強固なパスワード
>②Multi Factor Authentification(MFAと略される) 多要素認証 

では実際にAWSのコンソールから試してみましょう


##パスワードポリシー
パスワードをどの程度、強力な物にするかはコンソールの中の

IMA > アカウント設定

で設定する事ができます。

![スクリーンショット 2021-04-28 162622.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/20224ab0-4fed-84c6-ff0f-8e5100e5fb44.jpeg)

『Change』をクリックすると下のような画面になります。


![スクリーンショット 2021-04-28 162840.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/b509012b-268b-f52d-ccf4-277da92c090d.jpeg)

##MFA
パスワードを強固な物にしただけでは、まだハッカーにパスワードを盗まれたりする可能性も否定できません。

そこで、MFAも合わせて使います。

あなたの持っているスマホなどのデバイスにQRLコードで読み込んだカウントダウンタイマーのようなものを利用して、そこに表示される6桁の数字を入力します。(この記事では、Google Autheiticatorによる 多要素認証を説明します。)

Google Autheiticatorの入手は、携帯のAPP StoreにGoogle Autheiticatorと検索して探してみてください。

MFAでもセキュリティを強化する事によって

>①パスワードが盗まれる

>②携帯デバイスが盗まれる

と２つのことが起こらないと、他人がAWSにログインできないようにすることができます

![スクリーンショット 2021-04-28 164706.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/e6b12705-e348-d66d-2c20-09a04f7c4a25.jpeg)


上記のスクショで示しているように、『マイセキュリティ資格情報』をクリックします

少しスクロールすると、下のような画面になりますので、そこにある『MFAデバイスの割り当て』をクリックします

![スクリーンショット 2021-04-28 164950.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/0d52e235-c125-1cfe-4e90-8f5b1c8defd4.jpeg)

割り当てられるMFAデバイスのタイプは、Google Autheiticatorのみではありませんが、この記事では、Google Autheiticatorを使うと仮定して解説しますね。


![スクリーンショット 2021-04-28 165254.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/bdcd1108-4efb-969b-ca19-8fb3b350d260.jpeg)
『仮想MFAデバイス』をチェックして続行をクリック

![スクリーンショット 2021-04-28 165429.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/f2130c26-bdf5-16e5-9f5e-f15479d35361.jpeg)

>①あらかじめ入手したGoogle AutheiticatorのQRコードリーダーでQRコードを読み込み

>②10秒ごとに新しい6桁の数字が表示されるので

>③1回目の6桁と、その次に表示される6桁の数字をそれぞれ、MFAコードと書かれたボックスに入力します。


以上の設定をすると、再度ログインする際に、MFAコードも入力するように求められます。

その時はあなたのデバイスに表示されている6桁の数字を入力してくださいね。

#まとめ

今回の記事は以上で終わりにします。

次回も、また引き継きAWSについての記事を書いていきますね。
CloudFrontでタイムアウトによる504エラーを回避する方法

## まえおき

皆さん、こんにちは！
ハンズラボのサムです！

今回は私がCloudFrontを検証中に知った知ってたらちょっと役に立つかも？な小技を紹介させていただきます！

## 504 Error Origin Response Timeout

CloudFrontのOriginの設定項目に、【Origin Response Timeout】というOriginとの通信でタイムアウトになる時間を設定する項目があります。
![スクリーンショット 2021-04-28 17.15.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181414/d51ac0e1-c4e4-765d-5910-4f13ac87ca4b.png)
こちらの項目なのですが、上限値はMax 60sとなっており、ちょっと長めの処理や負荷がかかっている際に60sだと504 Errorで下記のような画面になることがあります。
![_2021-04-22_11.34.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181414/eeee6183-8944-df98-7cd4-bfb8f88a2fb0.png)
これは実はAWSサポートの【サービス制限の緩和】から【Origin Response Timeout】のMax時間を伸ばすことが出来きます！
ただ、これにも上限があって【60s -> 180s】が限界みたいです(ハードリミットらしい)
なので、万が一CloudFrontの【Origin Response Timeout】で引っかかるようなことがあれば是非この方法を試してみてください！
もっとも、そんなにレスポンスがかからないように構築しないといけないという考え方が普通なので、この方法はあくまでもどうしても困ったら試す程度だと思います。

以上、CloudFrontの小技？でした！
【Rails6】アプリ名を変更したい

開発中にrailsアプリ名を変更した際に行った手順です。
renameというgemを使用しました。　

# 開発環境
Rails 6.1.1
Ruby 2.7.2
mac 0S Big Sur 11.2.3

# renameを導入

Gemfileに以下を追記します。


```ruby:Gemfile
gem 'rename'
```
ターミナルでインストール。

```ruby:ターミナル
$ bundle install
```

インストールが確認できれば古い方のデータベースを破棄します。

```ruby:ターミナル
$ rails db:drop
```
# 変更したいアプリ名を入力
ここで renameのコマンドで新規のアプリ名を入力します。

```ruby:ターミナル
$ rails g rename:into 変更後のアプリ名
```

今回はold_app → new_appへ変更して以下の通りになりました。

```ruby:ターミナル
$ rails g rename:into new_app
Search and replace module in...
        gsub  config.ru
        gsub  README.md
        gsub  Rakefile
        gsub  yarn.lock
        gsub  babel.config.js
        gsub  package.json
        gsub  Gemfile
        gsub  Gemfile.lock
        gsub  postcss.config.js
        gsub  config/routes.rb
        gsub  config/environments/production.rb
        gsub  config/environments/development.rb
        gsub  config/environments/test.rb
        gsub  config/spring.rb
        gsub  config/environment.rb
        gsub  config/application.rb
        gsub  config/puma.rb
        gsub  config/boot.rb
        gsub  config/initializers/application_controller_renderer.rb
        gsub  config/initializers/backtrace_silencers.rb
        gsub  config/initializers/active_admin.rb
        gsub  config/initializers/mime_types.rb
        gsub  config/initializers/filter_parameter_logging.rb
        gsub  config/initializers/wrap_parameters.rb
        gsub  config/initializers/assets.rb
        gsub  config/initializers/cookies_serializer.rb
        gsub  config/initializers/devise.rb
        gsub  config/initializers/content_security_policy.rb
        gsub  config/initializers/inflections.rb
        gsub  config/initializers/session_store.rb
Error: No such file or directory @ rb_sysopen - /Users/*****/ディレクトリ名/old_app/config/initializers/session_store.rb
        gsub  config/database.yml
Renaming references...
Renaming directory...Done!
New application path is '/Users/*****/ディレクトリ名/new_app
```

ターミナルを再起動してアプリのディレクトリ名が変更できていれば成功です。
新規のデータベースを作成するのも忘れずに。

```ruby:ターミナル
$ rails db:create
```

```ruby:ターミナル
$ rails db:migrate
```
最後に`rails server`が起動するか確認します。

```ruby:ターミナル
$ rails s
```


# 追記
* アプリをGithubに連携している場合はGithub側でも変更が必要です。
* `package.json`、`HTML`で直接記載した旧アプリ名も別途変更が必要です。

# まとめ
アプリ名はなるべく変更しないよう計画的に運用したいですね！

参考:　[[Rails]rails newした後からアプリ名を変更する方法](https://qiita.com/ryoya-s/items/66e426f1a0dd5d87cd6f)
CSSの重複したプロパティや無効なプロパティを見つける

# 概要
開発でCSSを書いていて、重複したプロパティがあっても自分では気づけないことが多くあります。
意識するだけでは見つけられない余分なコードも、ツールを使って簡単に見つけらればいいなと思って探したところ便利なツールやサービスがあったので紹介します。

# Yellow Lab Tools
https://yellowlab.tools/result/fy3jxcv127

上記のサイト上でサービスのURLを入力するとWebパフォーマンスを調べてくれます。
その中に「Bad CSS」の「Duplicated properties」という項目があり、重複したプロパティの一覧を表示します。
![スクリーンショット 2021-04-28 16.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453689/85b0435c-a903-59a7-3ee9-cbdc19d66b96.png)
そのほかにセレクターの重複やCSSの複雑度なども表示してくれるのでCSS全体の見直しにも使用できると思います。
ただ、入力したURLのページで使用されているコンパイル済みのCSSだけを監査するので、SCSSなどで開発している場合は元ファイルのどこに記述されているか見つけにくいです。

# Chrome DevTools CSS Overflow
ChromeのDevToolsで使用できる実験的な機能の一つです。
有効にするには設定を開いて、ExperimentsタブにあるCSS overflowにチェックを入れます。
![スクリーンショット 2021-04-28 17.09.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453689/8fa1ff9a-43de-39d9-8d1e-01a600b3593c.png)

有効にすると「CSS Overflow」のタブが追加されるので、タブを開いて「Capture overflow」をクリックします。
![スクリーンショット 2021-04-28 11.45.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453689/a805c93a-4960-707f-f3ef-b604fddfcb74.png)
上の画像の通り、そのページでCSSで使用されているカラーの種類やフォント、メディアクエリなどを見ることができます。
Unused declarationsという項目で、設定しているけどCSSの仕様上、無効なプロパティを表示してくれます。

ただこのツールでは完全に機能しないプロパティだけを抽出するようです。
例えば、`position: static`が効いているときに`top、left`を設定したり、`display: block`の要素に`vertical-align`を設定することはCSSの仕様上まったく適用されないので抽出してくれます。
ですが、同じプロパティ名が重複しているといったことは判断して抽出してくれないみたいなので、先ほど述べた「Yellow Lab Tools」とうまく使い分ける必要があると思います。

# 参考
https://jser.info/2021/03/23/node.js-15.12.0fs.promises-strict-csp-css-auditing-tools/
https://www.smashingmagazine.com/2021/03/css-auditing-tools/

# おわり
紹介したツールは個人で簡単に利用することができるので、自分のコードに不安がある方はぜひ試してみてください。
深い階層構成のJavaScriptオブジェクトを設定する時に便利なset-valueメソッド

Immutable.js型だったら、`imtRecord.setIn(['a', 'b', 'c'], 'd');`のようにシンプル書けるが、純粋なJavaScriptオブジェクトなら、当然できない。

## 自分で頑張って描くなら、次のような感じだと思う。

- obj.aがあったら、その中にbを設定する
- obj.bがなかったら、まずobj.bに空オブジェクトを設置してから、bを中に設定する
- c以降も同様のロジックで繰り返す

## 便利そうなライブラリない？

何処でもいつでもこんなロジックが発生するから、ないとおかしい。
set-valueというライブライはgithubにある。

https://github.com/jonschlinkert/set-value

## set-valueの使い方

```
npm install set-value

// hoge.js
import set from 'set-value';

const obj = {};
set(obj, 'a.b.c', 'd');
console.log(obj);
// output: { a: { b: { c: 'd' } } }
```
Windows 版 Node.js 手動セットアップ手順

管理者権限が無い Windows 10 (64-bit) で Node.js を使うための手順です。

1. Web ブラウザーを開き, [Download | Node.js](https://nodejs.org/en/download/) にアクセスする。
1. **Windows Binary (.zip)** の **64-bit** をクリックし, アーカイブをダウンロードする。
1. ダウンロードしたアーカイブを展開し, C ドライブの直下に移動する。
    - 今回は `C:\node-v14.16.1-win-x64` というフォルダーに, `node.exe` や `npm.cmd` が存在するものとする。
1. [Windows 10 環境変数設定手順](https://qiita.com/ryo-sato/items/e24c81eca6ffe9db3fb0) を参考に,
   環境変数 **Path** に `C:\node-v14.16.1-win-x64` を追加する。
1. スタートメニューを右クリックし, **コマンド プロンプト** をクリックする。
    - コマンドプロンプトが開く。
1. `node --version` や `npm --version` と実行し, バージョン情報が表示されることを確認する。

    ```powershell
    > node --version
    v14.16.1

    > npm --version
    6.14.12
    ```


どっとはらい。
JUCEのCameraDemoサンプルをMacで動かす

# Projucer

File -> Open Example -> GUI -> CameraDemo
を選択。
デモのプロジェクトを開く。
![スクリーンショット 2021-04-28 16.38.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128735/3d2981ae-3df4-3d5f-68b1-79e2930a3178.png)

## Camera Access
![スクリーンショット 2021-04-28 16.34.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128735/072efce9-f410-2d5b-8d0f-0147a027798e.png)

Exporters > Xcode(macOS) -> Camera Access -> Enaled
にする。

Xcodeボタンを押す。

# XCode

適当に新しいフォルダを作って、Openボタンを押す。
XCodeのプロジェクトが作成される。

Product -> Run
をクリックして、ビルド、実行。

![スクリーンショット 2021-04-28 16.47.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128735/95faf4ba-527d-ae2c-1b95-89a004df120b.png)

カメラアクセスを許可。
![スクリーンショット 2021-04-28 16.57.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128735/46fe09c7-f834-44a4-be1a-f603bc369b0b.png)

カメラの画像が映る。

ちょい技術メモ
Portable 版 Git for Windows 64-bit インストール手順

管理者権限が無い Windows 10 で Git を使うための手順です。

1. Web ブラウザーを開き, [Git - Downloading Package](https://git-scm.com/download/win) にアクセスする。
1. **64-bit Git for Windows Portable** をクリックし, アーカイブをダウンロードする。
    - 拡張子が `.exe` ではなく, `.7z.exe` となっていることを確認する。
1. ダウンロードしたアーカイブを開く。
    - *Portable Git for Windows 64-bit* ウィンドウが開く。
1. *Where do you want to install portable Git?* 欄に `C:\PortableGit` と入力し, **OK** ボタンを押下する。
    - 展開が完了し, ウィンドウが自動的に閉じるまで待つ。
1. (オプション) Visual Studio Code など, 他のプログラムから Git を利用する場合, [Windows 10 環境変数設定手順](https://qiita.com/ryo-sato/items/e24c81eca6ffe9db3fb0) を参考に, 環境変数 `PATH` に `C:\PortableGit\bin` を追加する。
1. エクスプローラーで `C:\PortableGit` フォルダーを開き, **git-bash.exe** を右クリック,
   **スタート メニューにピン留めする** をクリックする。
1. スタートメニューより **git-bash** をクリックする。
    - **MINGW64:/** ウィンドウが開く。
1. `git --version` と入力し, 以下のようにバージョンが表示されることを確認する。

    ```
    git version 2.31.1.windows.1
    ```
    - バージョン情報は 2021-04-28 時点のもの。
    - `exit` で終了できる。


どっとはらい。
gitでタグをチェックアウトする

gitを使ってバージョンコントロールをする上で、GitHubのRelease機能を利用したりしてgitのtagは作成したものの、そのtagを打った際のコードに戻る（チェックアウトする）ことが少なかったので、その方法などを改めて確認しておきます。

## タグ一覧を確認

```zsh
git tag
```

このコマンドで作成されたタグが一覧になって表示されます

## 対象のタグをチェックアウト

```zsh
git checkout -b branchName refs/tags/tagName
```

## ついでに、現在のブランチの最新コミットでタグ作成方法

```zsh
git tag tagName
```

### タグにコメントを付ける場合

```zsh
git tag -a tagName -m 'comment'
```

↓の場合、コメント入力画面が表示されます

```zsh
git tag -a tagName
```

### 過去のコミットでタグを作成する場合

```zsh
git tag -a tagName -m 'comment' xxxxxxx
```

### 作成したタグをリモートリポジトリにPushする方法

```zsh
git push origin tagName
```

複数の場合

```zsh
git push origin --tags
```

## タグを削除する場合

```zsh
git tag -d tagName
```

### Push済の、リポジトリにあるタグを削除する場合

```zsh
git push origin :refs/tags/tagName
もしくは
git push --delete origin refs/tags/tagName
```
トレイリングクロージャ


トレイリングクロージャーとは、関数の引数の最後がクロージャの時、クロージャを()の外に書くことができる記法です。

```

func sample(parameter: Int, handler: (String) -> Void ) {
    handler("parameter is \(parameter)")
}

// トレイリングクロージャなし
sample(parameter: 1, handler: { string in
    print(string)
})

// トレイリングクロージャあり
sample(parameter: 1) { string in
    print(string)
}

```

トレイリングクロージャ記法を使用した方がコードがスッキリして可読性が上がります。
Xcodeで関数をかくとき、クロージャ部分をダブルクリックもしくはエンターすると自動的にトレイリングクロージャ記法にしてくれます。

また、引数が１つの時でもトレイリングクロージャは使用できます。その場合は関数呼び出しの（）も省略できます。

```
func sample(handler: (String) -> Void ) {
    handler("sample")
}

sample { string in
    print(string)
}
```

# 参考
[増補改訂第3版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plusシリーズ)
クロージャの属性


クロージャを関数や別のクロージャの引数として利用する場合にのみ有効な仕様として、属性とトレイリングクローリングがあります。

属性はクロージャの型の前に@属性名を追加して指定します。

```
func 関数名(引数名： @属性名　クロージャの型名) {
   関数呼び出し時に実行される文
}
```

# escaping属性

escaping属性は、関数に引数として渡されたクロージャが、関数のスコープ外で保持される可能性があることを示します。
コンパイラはescaping属性の有無によって、クロージャがキャプチャを行う必要があるかを判別します。

```
var queue = [() -> Void]()

func enqueue(operation: @escaping () -> Void) {
    queue.append(operation)
}

enqueue {
    print("executed")
}
enqueue {
    print("executed")
}

queue.forEach{ $0() }
```

上のプログラムでは、引数のクロージャは、関数のスコープ外で、保持されます。
なので、escaping属性を指定していないとエラーになります。

# autoclosure属性
引数をクロージャで包むことで、遅延評価を実現するための属性です。

```
func or(_ lhs: Bool, _ rhs: @autoclosure () -> Bool) -> Bool {
    if lhs {
        print("true")
        return true
    } else {
        let rhs = rhs()
        print(rhs)
        return rhs
    }
}

func lhs() -> Bool {
    print("lhs関数が実行されました")
    return true
}

func rhs() -> Bool {
    print("rhs関数が実行されました")
    return false
}

or(lhs(), rhs())
```

# 参考
[増補改訂第3版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plusシリーズ)
プロパティオブザーバ


# プロパティオブザーバとは
ストアドプロパティの値の変更を監視し、変更前と変更後に文を実行するものです。

# 基本構文

```
var プロパティ名 = 初期値 {
    willSet {
        プロパティの変更前に実行する文
        変更後の値には定数newValueとしてアクセスできる
    }
    
    didSet {
        プロパティの変更後に実行する文
    }
}
```

# サンプルコード

```
struct Greeting {
    var to = "Yoshida" {
        willSet {
            print("willSet: (to: \(self.to), newValue: \(newValue))")
        }
        
        didSet {
            print("didSet: (to: \(self.to))")
        }
    }
}

var greeting = Greeting()
greeting.to = "Yamada"
```

```
// 出力
willSet: (to: Yoshida, newValue: Yamada)
didSet: (to: Yamada)
```
レイジーストアドプロパティ


# レイジーストアドプロパティとは
アクセスされるまで初期化を遅延させるプロパティです。

# 基本構文

```
lazy var インスタンスプロパティ名：　プロパティの型　＝　式
static lazy var スタティックプロパティ名：　プロパティの型　＝　式
```

# サンプルコード

```
struct SomeStruct {
    var value: Int = {
        print("valueの値を生成します")
        return 1
    }()
    
    lazy var lazyValue: Int = {
        print("lazyValueの値を生成します")
        return 2
    }()
}

var someStruct = SomeStruct()
print("インスタンスを作成")
print("valueのアクセス", someStruct.value)
print("lazyValueのアクセス", someStruct.lazyValue)
```

```
// 出力
valueの値を生成します
インスタンスを作成
valueのアクセス 1
lazyValueの値を生成します
lazyValueのアクセス 2
```

# メリット
上の結果より、レイジーストアドプロパティはアクセスしたときに初期化されることがわかりました。
レイジーストアドプロパティを利用することで、初期化コストの高いプロパティの初期化をアクセスまで引き伸ばし、アプリのコスパを向上させることができます。

通常、ストアドプロパティの初期化時に、他のプロパティやメソッドを利用することはできません。
しかし、レイジーストアドプロパティはインスタンス生成より後に行われるため、初期化時に他のプロパティやインスタンスにアクセスすることができます。

```
struct SomeStruct {
    var value = 1
    lazy var lazyValue = double(of: value)
    
    func double(of value: Int) -> Int {
        return value * 2
    }
}
```

# 参考
[増補改訂第3版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plusシリーズ)
[GAS] 今日が土日・祝日であるかを判定する



```javascript
// 今日が休日(土日、祝日)か判定する関数
function todayIsHoliday(){
  //実行した当日の日付情報を取得する
  let today = new Date();
  //今日の曜日(0:日曜～6:土曜)を取得し、土日と判定された場合はtrueを返す
  let weekInt = today.getDay();
  
  //祝日を判定するため、日本の祝日を公開しているGoogleカレンダーと接続する 
  let calendarId = "ja.japanese#holiday@group.v.calendar.google.com"; 
  let calendar = CalendarApp.getCalendarById(calendarId); //翌日にイベントが設定されているか取得し、イベントが有る場合はtrueを返す 
  let todayEvents = calendar.getEventsForDay(today); 

  if(weekInt == 0 || 6 == weekInt){ 
    return true; 
  } 
  else if(todayEvents.length > 0){
    return true;
  }
  //土日、祝日のいずれでもない場合は、休日ではないとしてfalseを返す
  return false;
}

```
Active Data Guardスタンバイ・インスタンスで一時テーブル操作を試す（Oracle Database 19c)

Active Data Guard環境のスタンバイ・インスタンスは基本的には読み込み専用です。しかし一時テーブルに対する書き込みを行うことができます。この記事ではスタンバイ・インスタンスで一時テーブルを作成し、書き込み処理ができる条件を確認します。

# Active Data Guard 環境での操作 

GLOBAL TEMPORARY TABLEはActive Data Guardスタンバイ・インスタンスで作成、削除ができます。

```
SQL> SELECT DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

DATABASE_ROLE    OPEN_MODE
---------------- --------------------
PHYSICAL STANDBY READ ONLY WITH APPLY  

SQL> CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR2(10));

表が作成されました。

SQL> DROP TABLE gtemp1;

表が削除されました。
```

PRIVATE TEMPORARY TABLEもActive Data Guardスタンバイ・インスタンスで作成、削除できます。

```
SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp1(c1 NUMBER, c2 VARCHAR2(10));

表が作成されました。

SQL> DROP TABLE ora$ptt_temp1;

表が削除されました。
```

しかしリアルタイム適用を停止するとPRIVATE TEMPORARY TABLEのみ作成できます。


```
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

データベースが変更されました。

SQL> SELECT DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

DATABASE_ROLE    OPEN_MODE
---------------- --------------------
PHYSICAL STANDBY READ ONLY

SQL> CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR2(10));
CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR2(10))
*
行1でエラーが発生しました。:
ORA-16000:
データベースまたはプラガブル・データベースは読取り専用アクセスでオープンされてい
ます

SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp1 (c1 NUMBER, c2 VARCHAR2(10));

表が作成されました。
```

# DML Redirectの設定が有効な場合 
DML Redirectが有効な場合でもGLOBAL TEMPORARY TABLEは作成、削除できます。テーブルに対する更新DMLはスタンバイ・インスタンス上で実行されます。

```
SQL> ALTER SESSION ENABLE ADG_REDIRECT_DML;

セッションが変更されました。

SQL> CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR(10));

表が作成されました。

SQL> INSERT INTO gtemp1 SELECT LEVEL c1, 'data1' c2 FROM DUAL CONNECT BY LEVEL <=100;

100行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> DROP TABLE gtemp1;

表が削除されました。
```

一方でPRIVATE TEMPORARY TABLEの作成、削除は実行できますが、テーブルに対する更新DMLはプライマリ・インスタンスにリダイレクトされるため ORA-00942 エラーになります（プライマリ・インスタンスにはテーブルが存在しないので）。

```
SQL> CREATE PRIVATE TEMPORARY TABLE ora$ptt_temp1 (c1 NUMBER, c2 VARCHAR2(10));

表が作成されました。

SQL> INSERT INTO ora$ptt_temp1 SELECT LEVEL c1, 'data1' c2 FROM DUAL CONNECT BY LEVEL <= 100;
INSERT INTO ora$ptt_temp1 SELECT LEVEL c1, 'data1' c2 FROM DUAL CONNECT BY LEVEL <= 100
            *
行1でエラーが発生しました。:
ORA-00942: 表またはビューが存在しません。 ORA-02063:
先行のエラー・メッセージを参照してくださいline(ADGREDIRECT)。

SQL> DROP TABLE ora$ptt_temp1;

表が削除されました。
```

# プライマリ・インスタンスが停止している場合
GLOBAL TEMPORARY TABLEの作成や削除はプライマリ・インスタンスが稼働中の場合に限り成功します。
以下の例はプライマリ・インスタンスを停止した状態でGLOBAL TEMPORARY TABLEを作成しています。

```
SQL> CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR2(10));
CREATE GLOBAL TEMPORARY TABLE gtemp1(c1 NUMBER, c2 VARCHAR2(10))
*
行1でエラーが発生しました。:
ORA-03150: データベース・リンクの通信チャネルでend-of-fileが検出されました ORA-02063:
先行のエラー・メッセージを参照してくださいline(ADGREDIRECT)。
```

ただし既存のGLOBAL TEMPORARY TABLEに対する更新はエラーになりません。

```
SQL> INSERT INTO gtemp2 SELECT LEVEL c1, 'data1' c2 FROM DUAL CONNECT BY LEVEL <= 100;

100行が作成されました。

SQL> COMMIT;

コミットが完了しました。
```
PHPStanで配列を型としてチェックする新機能ができていた

PHPStan 0.12.84 で Local type aliases の機能が実装されたようだ。

元々、型のエイリアスの機能はあったんだけど、グローバル設定だった。
それがクラス用に定義できるようになったみたいだ。

https://phpstan.org/writing-php-code/phpdoc-types#local-type-aliases

```php
/**
 * @phpstan-type UserAddress array{street: string, city: string, zip: string}
 */
class User
{
	/**
	 * @var UserAddress
	 */
	private $address; // is of type array{street: string, city: string, zip: string}
}
```

```php
/**
 * @phpstan-import-type UserAddress from User
 */
class Order
{
	/** @var UserAddress */
	private $deliveryAddress; // is of type array{street: string, city: string, zip: string}
}
```

今から新しく作るプログラムで使う必要はないけど、古いプログラムで配列を多用していて型チェックできないと困っている場合には有効そうだ。
Windows Terminalで cmd.exeからの exitで tabを残さない

## Update

普通に対応できる方法が見つかりました。

- 分割されたWindowやTabが残ったときは CTRL+SHIFT+W で閉じれる
- プロファイル＞詳細設定にある、「プロファイルの終了動作」を「プロセスの終了、失敗、クラッシュ時に閉じる」にしておけば、そもそも残らない
  ![プロファイル設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128512/f74bbe08-7db4-6ee4-f33b-27b757933b9a.png)

## はじめに

私は Windows環境を CLIで操作するのですが、いまだに cmd.exe[^cmd] を使っています。
ただ、Windows Terminalを使っていると exitしたときに Tabが残ってしまうことがあり ちょっと鬱陶しいです。

[^cmd]: Power-Shell は Scriptを書くときには強力で良いのですが、普段使うには少し鬱陶しく感じてしまうので……。

↓ こんなの

![2021-04-28 12_13_21-CMD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128512/59280f80-7133-cbbf-8115-9b95c5e5f949.png)

これは exitの、終了コードが指定されないとき、cmd.exeが最後に得ていた終了コードを返すという仕様があるためです。
直前に入力したコマンドがエラー終了していた場合等、このような形で Tabが残留することになります。

このとき Tabの × にマウスカーソルを重ねると 「タブを閉じる(Ctrl+F4)」 と表示されるのですが、[単にCtrl+F4押しても閉じません](https://github.com/microsoft/terminal/issues/8585)。

Tabのタイトルをクリックしてフォーカスをそこに移すか、設定を入れる事で回避できますがマウスなりキー操作なりの追加操作が必要です。

EXITしたら 普通に消えて欲しいと思ったので、その方法です。

……もっと簡単に出来るんじゃない？って気もしてますので やり方あれば教えてください。

## 結論から

- Windows Terminal cmd.exeを /k doskey で マクロ設定を入れる
- マクロで EXIT=TYPE NUL & EXIT $* としてパラメータ無しEXITの終了コードを0にする

## EXITを終了コード無しで実行したときに 0 で終了させる

やりたいのは、たったこれだけの事なので面倒臭がらずに

```batch
exit 0
```

と打てば良いのではないかと思いますが、
exitを素で叩くのは既に30年身体にしみついてしまった習慣なので変えられません。

「exitするときは exit 0」と、自分ルールを決めたとしても、
exitだけ叩いてしまい、残ったtabを見る度にイラっとするのが目に見えています。

ならバッチファイルでも作れば？と思いますが

```batch:exit.cmd
@EXIT 0
```

これも内部コマンド優先なので exit.cmd は呼ばれないですし、
呼ばれたとしても exit.cmd の再帰ループが終わりません。

ではどうするかというと、

## doskey

そう、doskeyです。

このコマンド、見る度に DOSかよ！山岡さん[^2]にSM-DOSって叱られるよ！って思っちゃいますが、
素の cmd.exeで aliasを実現しようと思うとこれしかないのです。ksh[^3] とか無いし。

まずは Windows Terminalの設定で cmd.exe 起動時に doskey で macro を設定するようにします。

```json
{
    "commandline": "cmd.exe /k doskey /macrofile=\"%USERPROFILE%\\macros.txt\"",
    "hidden": false,
    "name": "CMD"
}
```

## マクロで EXIT=EXIT 0

あとは 終了コードを0にして exit すれば良いだけですので、マクロの設定ファイルに一行追加

```txt:macros.txt
EXIT=EXIT 0
```

これで良いといえば良いのですが、これだと逆に エラー終了が出来ないです。

設定入れたのを忘れて exit 1 して「あれ、エラー終了にならない？」とかなる
ありえそうにもない未来を予想してしまいます。

私がやりたいのは パラメータを省略したときの EXIT 0 です。

## ERRORLEVELを設定する

バッチファイル等で 終了コードを得るときは %ERRORLEVEL% と、環境変数参照のような書き方をします。

が、これはただの罠です。ERRORLEVELは 環境変数ではありません。

次の様なマクロを書いても目的は達成できません。

```txt:macros.txt
EXIT=SET ERRORLEVEL=0 & EXIT $*
```

それならと、こんな風に書いてみたのですが……

```txt:macros.txt
EXIT=CMD /C EXIT 0 & EXIT $*
```

なんか……これどうなん？
cmd.exe終わらせるために cmd.exeのプロセスを起動するの？　何それ？
と、心がざわつくのでもう少しなんとかしたいです。

そもそも CMD.EXEの内蔵コマンドって終了コード返さない事が結構あるし、
返すにしても 確実に 0 になるオペレーションって何か良い物が無いかな？と
思ってたどり着いたのが 以下です。

```txt:macros.txt
EXIT=TYPE NUL & EXIT $*
```

……TYPEなら内蔵コマンドだし。

この設定で、exitしたときに パラメータ指定をしなければ 0 で、
終了コードやオプションを指定したときは それに従って終了するようになります。

ちなみに文字数的には "CD ." で カレントフォルダへの移動も終了コードが設定されるので、
それでも良いかと思います。

## おまけ

chocolatey使って パッケージをインストールするとき等、
いちいち管理者権限得るのに右クリックしてWindows Terminal開きなおすの面倒臭い。

という方は以下のadminマクロみたいなのも一緒に定義しておくと
管理者権限 Windows Terminalをコマンドで開けます。

```txt:macros.txt
ADMIN=powershell -command start-process wt -verb runas
```

[^2]: 某漫画のキャラクター。mac狂信者。
[^3]: Un*xのkshではありません。正式名称は KI-Shell だったかな？。[vectorに残ってないかなと探してみた](https://www.vector.co.jp/vpack/filearea/dos/util/shell/ksh/)のですが見つかりませんでした
Jiraで課題を一括編集する

## はじめに
意外と知らない方が多い印象を受けるので、知っていれば便利！というJira課題の一括編集方法をご紹介します。

## 手順
① 編集したい課題のリストをフィルターや詳細検索を駆使して抽出します
今回は課題検索の方法で説明します

ページ上部のメニューバーから【課題】→【課題の検索】で検索画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/2d1c495d-7de9-f13e-7d7e-7fd063d4dcf1.png)

② JQLもしくはベーシック検索で対象の課題一覧を検索します。
※最初はベーシックで検索したほうが分かりやすいかもしれません

今回は「テストプロジェクト」内の課題から「優先度」が高以上の課題を抽出します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/f1c9795e-5453-533b-2587-dd58f00ac626.png)
JQLはこんな感じ

```
project = TEST AND priority in (Highest, High)
```
③ 抽出ができたら右上の【ツール】から「全４件の課題」を一括変更をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/fd23d424-83d8-26b9-c855-616d456a1b0e.png)

④ 一括変更のメニューが表示されるのですべての課題にチェックを付けて次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/30b8b126-b41a-e08b-685a-934bc9dff75f.png)

⑤ 続いては操作の選択です
今回は課題の編集をしたいので「課題の編集」を選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/95d8322f-2e12-a7a4-0f21-c30a21a8c709.png)

⑥ 課題のどのフィールドを編集するか選択できますので今回は「優先度」をMediumに、担当者を自分に設定してみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/1b21bba9-23cc-7441-5908-22658fb01bab.png)

画面の最下部に通知設定の項目がありますが、すべてオフが推奨です（報告者などに大量に通知が送られることを防ぐため）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/e22273a4-b07a-54c0-f669-73ba319129f3.png)
編集する項目と通知設定をしたら次へ

⑦ 最終確認をして実行！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/1a21312f-5dab-56d2-ca09-5b126d6053c7.png)

4件の課題が無事一括編集できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/1fe552db-9da8-ee07-537b-9ad0b59ecf02.png)

## まとめ
今回紹介した課題の編集だけではなくトランジションを実行してステータスを遷移させたり、間違えて別のプロジェクトに作成しまった課題（あるある）を正しいプロジェクトに一括移動したりと様々なことができます。

以上、参考になれば幸いです。

公式ドキュメント：https://ja.confluence.atlassian.com/jiracoreserver/editing-multiple-issues-at-the-same-time-939937916.html
`String.prototype.split`で区切り文字を複数使いたい場合の書き方

[以前](https://qiita.com/NagayamaToshiaki/items/473175fde0dd8e3d2f2f)書いた内容の抜粋だが、本題と離れた話かつ、どう考えても検索に引っかからないので仕切り直し。さらに動作原理について可能な限り詳しく書く。

`The quick brown fox jumps over the lazy dog.`という文字列を`fox`もしくは`dog`のどちらかで`split`させて、なおかつ両方とも`split`の内容として残したい場合、正規表現はこう書く。

```javascript:split.js
"The quick brown fox jumps over the lazy dog.".split(/(fox|dog)/)
```

しかしこれでは、`fox`や`dog`の代わりに長い正規表現になった場合区切りが見つかりづらくなる。明示的に2つの正規表現が区切れていることを示すにはどうすればよいのだろうか。

#車輪の再発明
まず考えたこととしては、`fox`と`dog`を正規表現で並立させることである。[正規表現で区切り文字を残すには表現を括弧で囲めばいい](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split "String.prototype.split() - JavaScript | MDN")。これを素直に書けば以下の様になる。
`(fox)|(dog)`
しかし、これで検索すると以下の様な結果が返ってくる。

```:(fox)|(dog)でsplitした結果
Array ["The quick brown ", "fox", undefined, " jumps over the lazy ", undefined, "dog", "."]
```

なに、`Undefinded`だと？　と筆者は最初たじろいでしまった。しかし種が分かればそう慌てるものでもない。
要は`split`では両方の要素を検索するわけだ。最初の`fox`が引っかかった時についでに`dog`も調べられ、見つからないから`undefined`となってしまうのだ。これは`dog`とマッチした際にも発生する。

では、`((fox)|(dog))`とした場合はどうなるのか。まず結果を想像してほしい。きっと実際のものとは違うものになるはずだ。

<details><summary>`((fox)|(dog))`で`split`した結果</summary><div>

```:((fox)|(dog))でsplitした結果
Array ["The quick brown ", "fox", "fox", undefined, " jumps over the lazy ", "dog", undefined, "dog", "."]
```

なんと大きな括弧のマッチング結果→個別の括弧のマッチング結果という分け方になってしまった！
</div></details>
あなたの考えと合っていましたか？　大当たり？　そいつは良かった。

#非キャプチャリング括弧
「やっぱ正規表現は難しいわ…」と、思わず弱音を吐きそうになるが、実は正規表現には面白い機能がある。それが「非キャプチャリング括弧」だ。
この機能は、括弧内に`?:`と書くことで発動し、括弧の内容に「[マッチしますが、マッチした内容は記憶しません](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions "正規表現 - JavaScript | MDN")」。今回の場合どんな意味があるかというと、具体例を見ていただこう。

```:(?&#58;fox)|(?&#58;dog)でsplitした結果
Array ["The quick brown ", " jumps over the lazy ", "."]
```

これは、区切り文字を`fox|dog`と指定した場合と同じだ。ということは、最初に示した例と同様の書き方をしてみると…

```:((?&#58;fox)|(?&#58;dog))でsplitした結果
Array ["The quick brown ", "fox", " jumps over the lazy ", "dog", "."]
```

つまり、最初の目的を達成する書き方は`((?:fox)|(?:dog))`である。無駄に遠回りをしているが、これで`split`の区切りが分かりやすくなった！　…はずだ。