次ログ

次ログ

ゆるりと働いているSREの技術ブログのような何か。趣味の話も書く

Manjaro Linux (Arch Linux)でWacomのFinger touchデバイスをxsetwacomで無効化できなかったのを解消したメモ

つい最近、OSをUbuntuからManjaroLinux i3に変更しました。 変更前に使っていたWacomのFinger touchの無効化エイリアスが機能しなくなりました。 結果としては解消したので備忘録メモをば。

移行前に使っていたエイリアス

移行前は以下のエイリアス~/.bashrc にセットして手動で呼び出して無効化してい ました。

alias wacomoff='xsetwacom set "Wacom Intuos Pro M Finger touch" Touch off'

しかしながら、Arch Linuxに移行してこのエイリアスを呼び出しても無効化できなくなっていました。

xsetwacomでデバイスを調べる

Linux Wacom」とかでググったら出てくる xsetwacom コマンドを使って調べます。 以下のコマンドを実行して確認しました。

% xsetwacom list                            
Wacom Intuos Pro M Pen stylus       id: 10  type: STYLUS    
Wacom Intuos Pro M Pad pad          id: 11  type: PAD       
Wacom Intuos Pro M Pen eraser       id: 28  type: ERASER    
Wacom Intuos Pro M Pen cursor       id: 29  type: CURSOR    

前述のエイリアスに指定していた「Finger touch」というデバイスが認識されていないように見えます。 しかしながら、この時点では指でタブレットを触れても反応しています。

xinputでデバイスを調べる

xsetwacomはwacomのデバイスを操作できますが、 指で操作できているのでデバイスは認識されていると考えました。 ということでWacomに限らず、接続されているデバイスすべてを操作、参照できるコマンドがないか調べました。

結果としてxinputというコマンドで問題を解消しました。

こちらでも前述のxsetwacomと同様にデバイス一覧を出力できます。 以下のコマンドを実行して調べました。

% xinput list | grep Wacom
⎜   ↳ Wacom Intuos Pro M Pen stylus             id=10   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos Pro M Pad pad                id=11   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos Pro M Finger                 id=12   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos Pro M Pen eraser             id=28   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos Pro M Pen cursor             id=29   [slave  pointer  (2)]

すると、xsetwacomでは見つからなかった「Wacom Intuos Pro M Finger」が見つかりました。 xsetwacomでは細かい値の変更ができるはずですが、無効化にするだけならこれを disableにすれば十分だと考えました。

以下のコマンドを実行して、指でのタッチを無効化することができました。

xinput disable "Wacom Intuos Pro M Finger"

根本解決にはなっていないですが、とりあえずこれで指タッチだけは無効化の目的は達成できました。

以上です。

AnbilePlaybookでプライベートの開発環境構築を一撃で終わらせられるようにした

普段自分が使ってる自宅PCの開発環境構築をコマンド一撃で終わらせられるようにした。

リポジトリはこちら。

setup : https://github.com/jiro4989/setup

なぜやったか

僕は不定期にPCのOSを変更したくなります。 今までUbuntuCentOS、LinuxMint、Debian、ManjaroLinuxなど色々変更し、 今ではManjaroLinux i3に落ち着いています。

数ヶ月に一度環境を構築し直しているわけですが、 最初の1回しかやらないことも多くて何をインストールしたのか忘れてしまいます。

Vimの環境構築とか何やってたのか覚えてなかったりするので どうせLinux系OSを使うならセットアップを自動化しよう、と考えました。

シェルではだめなのか

AnsiblePlaybookを使っていますが、最初はシェルで書いていました。 curl URL | shで環境構築が終わるような感じです。これはこれで便利でした。

しかしながらOSをごとに使うコマンドが違ったり、 このOSにはこのコマンドがないので追加でインストールが必要、みたいな ことが度々あって、それを分岐させるのが大変でした。

ロール(タスクのまとまり)で分ける、というアプローチが取りづらかったんです。

Ansibleに変更して、最初にAnsibleをインストールする手間が発生してしまいましたが、 それ以外はとても快適につかえています。

参考になったリンク

Ansibleはまともに動かせるようになるまでに時間がかかる。 覚えることも多いです。 ということでまともにかけるようになるまでに参考にした記事を記載。 僕がわざわざ書くよりも、今はWebに情報が豊富になっているので。

はてなブックマークの自分のansibleタグのページです。

https://b.hatena.ne.jp/jiroron666/search?q=ansible

特に参考になったのはこの記事。

Ansibleをはじめる人に。 - Qiita

最後に

Ansibleでローカル開発環境構築自動化するのいいよ、というだけの話でした。

Ansibleをおすすめする記事で必ず見かける「べき統制」「設定ファイルベース」 という点は、こうして自分でずっとメンテし続けるとたしかにメリットを体感します。

あの記述どうやったっけ、ってのをさっとコピペして使い回せますし、 何回も実行できますからね。

こうして自動化するスクリプトを作っておくことのメリットは 1つは自動化による環境構築コストの低下ですが、 もう1つは構築漏れがなくなることだと思います。

結構、OS入れ直して実行してみたら失敗することありました。 が、都度修正すればいいですし、大半は動くので修正量は少ないです。

個人開発機ですし完全な自動化はできてなくても、 設定しないといけない物事について、設定ファイルとしてまとまっていることが大事です。

なので、Ansibleでなくてもよいので 自分の開発機の環境構築スクリプトとかは用意しとくと いいと思います。

シェル芸bot環境につぶやいてきたジョークシェル芸をひたすら書き連ねる

今までシェル芸botで実行してきたシェルのうち ボクが気に入ったものや、メモしておきたいものをひたすらここに残します。

ついでにどういうことをやっているのかといった解説もします。

LISP風の条件分岐を行う関数

[ifという関数を定義して]が見つかるまでをシェルのコマンドとみなす。 結果的に内部でifしてるんですけれどね。一応true、falseで実行されるコマンドが変化する。

[if(){
f=2
a=()
b=()
c=()
i=0
for o in "$@";do
case "$o" in
[)f=1;;
])f=2;let i++;;
*)
if [ $f = 1 ];then
case $i in
0)a+=($o);;
1)b+=($o);;
2)c+=($o);;
esac
fi
;;
esac
done
if $("${a[@]}");then
eval ${b[@]}
else
eval ${c[@]}
fi
}
[if [ true ] [ echo 1 ] [ echo 2 ] ]
#シェル芸

喘ぎ声生成

いわゆるみさくらなんこつ的な喘ぎ声っぽいなにかを生成するシェル芸。 下品すぎる。

p(){
paste -d "" - - - - - -
}
h(){
head -n 99
}
s(){
shuf -re $@
}
(s あ ぁ ん ♥ \"|p|grep -vE '^("|♥)'|h;
s ら め へ ぇ \"|p|grep -vEe '""|らら|めめ'|grep -E "^ら"|h;
s ん ほ お ぉ \"|p|grep -E "^ん"|h;
s い く ぅ \"|p|grep -E '^い'|grep -v '""'|h;)|shuf
らへめ"ら"
い"くぅ"く
ん"ぉんぉお
ぁぁぁあ♥ん
らぇへめ"ぇ
い"いくくく
らへへ"めら
ん""ん"ぁ
んおお"んお
いくいぅ"く
らへ"へめへ
らぇぇめぇぇ

「あなたは赤い部屋が好きですか」1文字ずつ増やして出力

かなり昔に作成されたホラーフラッシュの赤い部屋の最後の方で表示される 少しずつ文字が見えていくというのを再現したシェル(もとのフラッシュだと文字と文字の切れ目から出現していたが)。

本家の赤い部屋フラッシュはもう見れない。 公開が停止されている、という意味ではなく、 ブラウザがフラッシュプラグインをサポートしていないため。 Youtubeで我慢する。

これを当時見たときは本気で怖がっていたような記憶。

echo あなたは赤い部屋が好きですか? | grep -o . | awk '{s=s""$1; print s}'
あ
あな
あなた
あなたは
あなたは赤
あなたは赤い
あなたは赤い部
あなたは赤い部屋
あなたは赤い部屋が
あなたは赤い部屋が好
あなたは赤い部屋が好き
あなたは赤い部屋が好きで
あなたは赤い部屋が好きです
あなたは赤い部屋が好きですか
あなたは赤い部屋が好きですか?

技術的な話をすると、grep -o .は文字列を1列にする。 -oオプションはマッチした文字だけを出力する。 .正規表現での「任意の何らかの文字」にマッチする。 よって、あらゆる文字が1つマッチしたら出力し、次のマッチを待つようになる。

以下の例を示す。

[0-9]は数値にのみにマッチする正規表現。 結果も数値のみ出力されている。

% echo あ12い34う56え78お | grep -Eo "[0-9]" 
1
2
3
4
5
6
7
8

対して.ではすべての文字が1文字ずつ出力されている。

% echo あ12い34う56え78お | grep -o "." 
あ
1
2
い
3
4
う
5
6
え
7
8
お

最後はawkで1文字ずつ連結して出力する。

awkでは文字列の連結は+とかは不要。 文字列や変数をカンマで区切ったらスペース区切り出力され、 カンマをつけずに文字列や変数を続けてprintすると 文字列が連結される。

awk '{s=s""$1; print s}'

なので、こう書いても同じ結果になる。

awk '{s=s $1; print s}'

うんこで囲う

シェル芸bot環境に存在するいくつかのコマンドと組み合わせている。 手前味噌だけれど、alignという自作のコマンドも使用している。

(
  echo;
  (
    unko.tower -s うんこ神 5 \
    | align left -p " " \
    | owari kan -gi; echo
  ) \
  | align center -p1 -n 60 \
  | sed -r 's/111/うんこ/g;s/11/うん/g;s/1/う/g';echo
) \
| align center -p2 -n 72 \
| sed 's/222/ウンコ/g;s/22/ウン/g;s/2/ウ/g' \
| sed 'y/NHK/うんこ/' \
| imgout #シェル芸

unko.towerはsuper_unkoリポジトリのコマンドの1つ。 -sオプションではうんこの中にテキストを埋め込める。 alignはテキストの位置を揃える。 owariはギコネコが看板を背負っているAAを出力する。 -giでは標準入力を受け取って、看板内に中央寄せして埋め込んで出力する。

$ unko.tower -s うんこ | align left | owari kan -gi

| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|
|       人          |
|     (うんこ)      |
|    (うんこうん)    |
|   (こうんこうんこ)  |
|       制作・著作       |
|   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄  |
|        N H K        |
|____________|
       ∧∧ ||        
      ( ゚д゚)||       
       /   づΦ        

一番深い階層でギコネコを出力するが、それ全体をサブシェルでラッピングし、 サブシェルをパイプしてalignに渡すことで結果全体を一揃えしている。

同じようなことを繰り返し、空白文字をうんこに置換。 sedのyコマンドでは1文字ずつ対応するように置換する。

相関図

これは2ツイート連携で実現している。280文字以内には収まった。

やっていることは結局前述のうんこで囲むのと同じことを組み合わせているだけ。

#!/bin/bash

(
echo
echo 'うんこシェル芸人とショル力の相関'|align center -n 70 -p ' '
(
echo 'y (シェル芸力)'
(
seq 10|while read i;do printf "%${i}s\n" '/';done|tac|sed 's/ / /g' | align left -p ' ' | sed -r 's/^/|/g'
echo
) | align left -p '~~' \
  | sed '11s/$/ x (うんこと呟く頻度)/g'
) \
| align left -n 40 -p ' ' \
| align center -p ' ' -n 70
echo '※1 サンプリング数:255名'|align right -n 70 -p ' '
echo
) | align center -p '-' -n 80

以下抜粋。 seq〜printfで空白埋めされた線を描画している。左上から右下に下がるように描画される。 線は斜め上に上がってほしかったので、whileの結果全体をtacで反転されている。 taccatの逆で、入力データの最終行から最初の行に向かって出力するコマンド。

$ seq 10 \
| while read i; do
    printf "%${i}s\n" '/'
  done \
| tac \
| sed 's/ / /g' \
| align left -p ' ' \
| sed -r 's/^/|/g'

|         /
|        / 
|       /  
|      /   
|     /    
|    /     
|   /      
|  /       
| /        
|/         

難読化うんこ

超絶読みづらくしたunko.tower。解説するのがしんどい。

+() { ! :;bc<<<obase=$?$#\;ibase=$(($?<<$?))\;${@:${?}:${?}}; };
$(echo -e "\x`! :;+ $?$?$?``! :;+ $?$?`\x`! :;+ $?$?$#``! :;+ $?$#$?`\x`! :;+ $?$?$#``! :;+ $?$#$#`") `! :`$((($?<<$?)+$?))$(echo -e "\x`! :;+ $?$?$?``! :;+ $?$?`")/     / ・__・ / <(unko.tower) #シェル芸


     人
   (   )
  ( ・__・ )
 (       )

+()はただの関数定義。関数名を+としている。 中でやっているのはbcコマンドに<<<(ヒアストリング)でbc用の式を渡している。

+の関数内の先頭の! :;$?を1にするための処理。 $(($?<<$?))bashの算術演算式で、左シフトを表現している。 よって$(($?<<$?))$((1<<1))になり、1の1左シフトで2になる。

あとのecho -eのところは、16進数で表現したsedコマンド。 ただし直接sedとしたくなかったので、echo -eで16進表現(\xFFみたいな)を文字に変換している。

あみだ線生成

あみだくじを生成する。 アルゴリズムが適当なので総当りで文字を生成して、余計なものが混じってる行を出力しないようにしているので 計算量は増えがち。 あみだくじの線の数を増やしたら出力されないほうが多くなる。

make_row() {
  seq $1 \
    | xargs -I@ bash -c 'printf "$(shuf -n1 -e ├ ┤ │)"' \
    | grep -vEe "├([^┤]|$)" -e "(^|[^├])┤"
  return $?
}

row=5
col=6

n=0
while [ $n -lt $row ]; do
  ! make_row $col
  n=$((n+$?))
done
├┤├┤││
││││├┤
││││├┤
├┤│├┤│
│├┤├┤│

やってることとしては、make_row関数であみだくじを生成し、その戻り値で あみだくじが生成されたかどうかを判定し加算し続けるというもの。 指定の数になったらwhileを抜ける。

grepは指定の文字が1つも見つからなかったときに終了コードが1になる。 1つでも文字が見つかった場合は終了コードが0になる。

今回のケースではその性質を利用し、あみだくじが出力されたとき、 「1行あみだくじの行を生成した」ということとして 生成した行数1を戻り値として返すということをやっている。

呼び出し元で!を使って0を1に反転しているので、 grepで行が見つかった際に1加算している。 (不正なくじが生成されていない)

終了コードの使い方としてはよろしくないアプローチだとは思う。

虹色のうんこ

super_unkoのunko.printpnmという自作のコマンドで出力したうんこのテキストを虹色に変換している。 PNMについてはWikipediaが参考になる。

a=("255 0 0" "255 165 0" "255 255 0" "0 128 0" "0 255 255" "0 0 255" "128 0 128")
i=0
while read -r line
do
  i=$((++i))
  sed -r 's/255 255 255/'"${a[$((i%7))]}"'/g' <<< "$line"
done <<< "$(unko.printpnm)" \
| convert - -scale 200x200 /images/t.png
#シェル芸

whileに対してヒアドキュメントを渡すところから処理が始まる。 パイプでwhileに渡していないことには理由があって、iというループカウンタを加算したいから。

パイプ後で実行されるコマンドは別シェルとして起動されるため、 その中で変数を定義したり値を変更しても、while外の変数には影響を与えない。

ループカウンタiは0〜6の値をループさせたいのでパイプは使えない、ということで ヒアドキュメントで渡している。

ループカウンタは虹色のRGBを定義した配列から色を取り出すときに使用している。 sedでもとの色の指定の箇所をループの都度sedの式を配列の色をもとに生成して置換している。

convert -ではパイプの結果を入力データとして利用することを指定している。 それをPNGとして保存する。

ちなみにwhileにテキストを渡す方法にはいくつかアプローチがある。 ファイルをいきなり渡したりコマンドの実行結果を渡したりパイプで渡したり いろいろ方法がある。 いくつかやり方を知っていると芸の幅が広がる。以下はその一例。

パイプせずにファイルをwhileに渡す

while read -r line; do
  echo $line
done < text.txt

パイプしてファイルを渡す

cat text.txt | while read -r line; do
  echo $line
done

パイプせずに複数行のテキストを渡す

while read -r line; do
  echo $line
done << EOS
1
22
333
EOS

パイプせずにコマンドの実行結果を渡す

while read -r line; do
  echo $line
done <<< "$(seq 3)"

色のついたテキストを画像に変換する

手前味噌で恐縮だが、textimgという自作のコマンドを使う。 これは渡されたテキストのエスケープシーケンスを解析してRGB値に変換して画像出力するコマンド。 シェル芸bot環境で画像を描画したくて作った。

bigunko.show | textimg -o /images/t.png

シェル芸bot環境では以下のように短くかける。

bigunko.show | textimg -s

grepの結果やscreenfetchなどの結果も画像に反映できる。

screenfetch | textimg -s

ちなみに上にスクロールできるオプションがある。

殺意のうんこ

前述のbigunko.showの色を変更して赤黒い配色に変更するシェル。

bigunko.show \
| sed 's/100/0/g;s/94/16/g;s/58/1/g;s/243/0/g' \
| sed 's/\x1b\[0m$//g;:a;s/ /う/;s/ /ん/;s/ /こ/;/ $/ba;s/[うんこ]/\x1b[31m&/g' \
| textimg -s
#シェル芸

bigunko.showの結果をlessで確認してみるとESC[48;5;243mとかって文字が大量に表示される。

これは端末上で背景色の変更を表現するエスケープシーケンス。 ESC[4nから始まると背景色、ESC[3nから始まると文字色が変わる。 このシェルでやっているsedはこのエスケープシーケンスの数値を別の色の数値に置換する。

置換が終わったら全角空白文字をうんこ文字に置換する。 文字色を変更するためESC[31を文字の置換に指定する。

色のエスケープシーケンスについて

前述のESC[48;とかって文字を端末上で再現する場合は\x1b[48あるいは\e[48と書く。 色だけ試したい場合は以下のシェルを実行してみるととりあえず色は見れる。

for i in 3 4; do
  for j in {0..7}; do
    echo -ne "\e[${i}${j}m  test  \e[m"
  done
  echo
done

ESC[3nは文字の色を変更する。 ESC[4nは文字の背景色を変更する。

nの値は0~8になる。0~7については色が固定だが、8を指定するとさらに別の色を指定できるようになる。

0~7の色についてはQiitaの記事 とかを見ればすぐに見つかる。

で、8の指定は特殊。 8を指定した場合は2通りの色の指定の仕方がある。 書式は以下の通り。

分類 ESC ESC 色指定
文字色 ESC[38 (固定) 5 (固定) 0 ~ 255m ESC[38;5;128m
背景色 ESC[48 (固定) 5 (固定) 0 ~ 255m ESC[48;5;128m

0〜255の色の一覧は下記の通り。

もう1つはRGB指定する方法。

きもいオジサンのLINEメッセージ

先日(2019/05/31だったかな)ojichatというコマンドがシェル芸bot環境に追加された。 これはLINEやTwitterなどのSNSで女性に対して下心丸出しのおっさんが送るメッセージを再現するコマンド。 以下のように実行する。

ojichat

ヤエ、そっちも雨なのかな( ̄ー ̄?)⁉出張で広島に行ってきたよ😍💕😄観光でも、行きたいなぁ💗💗モチロン、ヤエとネ

ojichat 花子

花子チャン、お疲れ様〜😃(^o^)😃✋今日は長崎28度だよ😱💦^^;💔暑いよ^^;💔ヤケドしないように気をつけないトネ(^_^)😃☀ (笑)

文章は完全にランダムに生成されるので、特定のパターンがほしいときはheadする。 以下は10回ojichatを実行する。

yes ojichat | head | bash

これを利用して特定の文言が出現するパターンを取得して文章を書き換えて独自の文章を作ったり。

メンヘラおじさん。

m=$(seq 100 | xargs -I@ printf "なんで")
yes ojichat \
| head -n 100 \
| bash \
| grep こうよ \
| head -n 1 \
| sed -E 's/こうよ.*/こうよ・・・。行かないの?なんで・・・'$m'/g'

#シェル芸
マキちゃん、オハヨウ〜😚😃😃♥ ちょっと電話できるカナ✋❓⁉⁉そろそろご飯行こうよ・・・。行かないの?なんで・・・なんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなんでなん

別の文章と合わせたりして色々遊べる。

きもいオジサンのメッセージをうんこに埋め込む

殺意のうんこシェル芸と同じようなことをやっている。

bigunko.showに含まれる文字を埋め込むには少し工夫が必要。 bigunko.showの全角スペースの前後にはエスケープシーケンスがついているため 「全角文字の連続」みたいな正規表現はかけない。

今回の僕のアプローチは「sedの置換式文字列をループで回し、bigunko.showが書かれた テキストを都度上書きして1文字ずつ全角空白を置換する」というようにした。

前述のシェルを分解すると以下のような3つのシェルに分解できる。

bigunko.show \
| tr '\n' 'Q' > a.txt

for __ in {1..20} do
  for cmd in $(ojichat | grep -o . | sed -E "s,.,s/ /&/ ,g" | tr -d "\n"); do
    sed -i "$cmd" a.txt
  done
done

cat a.txt|tr Q \\n \
| sed -E 's@\x1b\[48;5;243m@\x1b[41m@g;s@.*@\x1b[30m&\x1b[m@g'\
| textimg -s

#シェル芸

まずbigunko.showをテキストファイルに出力する。 このとき改行文字を元の文章に出現しない何でも良い文字に置換して1行のデータに変換している。 sedのループで置換するときに1行のデータのほうが処理しやすいため。

bigunko.show \
| tr '\n' 'Q' > a.txt

sedで文字を置換する処理。 sed -E "s,.,s/ /&/ ,g"の箇所でsedの式を生成している。

for __ in {1..20} do
  for cmd in $(ojichat | grep -o . | sed -E "s,.,s/ /&/ ,g" | tr -d "\n"); do
    sed -i "$cmd" a.txt
  done
done

sedの結果を一旦出力すると次のようになる。

% ojichat | grep -o . | sed -E 's,.,s/ /&/ ,g' | tr -d \\n
s/ /は/ s/ /つ/ s/ /か/ s/ /チ/ s/ /ャ/ s/ /ン/ s/ /、/ s/ /ヤ/ s/ /ッ/ s/ /ホ/ s/ /ー/ s/ /(/ s/ /^/ s/ /o/ s/ /^/ s/ /)/ s/ /😃/ s/ /😃/ s/ /♥/ s/ / / s/ /😄/ s/ /何/ s/ /し/ s/ /て/ s/ /る/ s/ /の/ s/ /か/ s/ /い/ s/ /❓/ s/ /早/ s/ /く/ s/ /会/ s/ /い/ s/ /た/ s/ /イ/ s/ /ナ/ s/ /😄/ s/ /💕/

sed&はマッチした文字列をそのまま埋め込む特殊な値。 後方参照みたいなもの。よく使う。

この結果をcmdにセットし、sed -iの式として利用している。 -iオプションでファイルを置換した結果で上書きできる。 分解すると以下のようなsedとして実行されている。

sed -i "s/ /は/" a.txt
sed -i "s/ /つ/" a.txt

最後に結合。最初の処理で1行のデータにしていたものをもとに戻す。 sedの式では、bigunko.showの背景色を赤色のエスケープシーケンスに置換している。

cat a.txt|tr Q \\n \
| sed -E 's@\x1b\[48;5;243m@\x1b[41m@g;s@.*@\x1b[30m&\x1b[m@g'\
| textimg -s

あとこのシェルだけでなくシェル芸botではよくやってしまうが、 sedで複数の式を一気に書いている。

sed -E 's@\x1b\[48;5;243m@\x1b[41m@g;s@.*@\x1b[30m&\x1b[m@g'\

圧縮されていて読みにくいが、複数のsコマンドをここでは実行している。 ;が式の区切り文字である。 実はあまり知らない人多いと思うが、sedは複数の式を同時にかけるし、何なら複数行に書くこともできる。

echo あいう | sed 's/い/i/; s/i/Z/'

あzう

これも結局は以下のシェルと同じである。

% echo あいう | sed 's/い/i/      
s/i/Z/
'

あZう

割とあまり一般的でない特殊なシェルを書いたような気がする。(シェル芸では一般的 なテクニックかもしれないが、普通のサーバオペレーションではまずやらないようなシ ェルの使い方であることは間違いない)

以上です。

Nimで文字幅を扱うためのライブラリ(eastasianwidth)を作った

Nimで文字幅を扱うためのライブラリ(eastasianwidth)を作りました。 なぜ作ったのか、と何ができるのか、について記載します。

EastAsianWidthとは

東アジアの文字幅の問題 - Wikipediaという名称で知られている 文字幅についてのヒントのことです。

いわゆる半角文字は半角1文字分、全角文字は半角2文字分の幅になるということを定義化したものです。 その他にも文字の分類について定義しています。

なぜ作ったのか

CLIツールを作る上で全角文字の幅を考慮した実装の必要があったためです。 Goだとサードパーティのライブラリでgo-runewidthがそれを実現できるのですが Nimにはこれに相当するものがありませんでした。

なので、Node.js用のライブラリeastasianwidthを参考に Nimにも実装してみた次第です。

何が問題になるのか

例えばプログラムでテキストを使用して罫線などを表現するケースを考えます。 テーブルを表現する罫線を引き、セル内にテキストを書くとき、 文字幅を考慮しないでプログラムから扱おうとすると罫線の位置がずれてしまいます。

問題になるケースの実装を示します。

from eastasianwidth import stringWidth
from sequtils import mapIt
from strutils import repeat
from unicode import runeLen

let texts = ["test code", "テストコード"]

echo """
string.len pattern
------------------
"""

# 文字の長さ(byteサイズ)のみで実装
let maxByteLen = texts.mapIt(it.len).max
for text in texts:
  let diff = maxByteLen - text.len
  let pad = " ".repeat(diff)
  echo "| " & text & pad & " |"

echo """

string.runeLen pattern
----------------------
"""

# rune文字の長さでの実装
let maxRuneLen = texts.mapIt(it.runeLen).max
for text in texts:
  let diff = maxRuneLen - text.runeLen
  let pad = " ".repeat(diff)
  echo "| " & text & pad & " |"

echo """

string.stringWidth pattern
----------------------
"""

# eastasianwidthを使用した、表示上の幅を考慮した実装
let maxStringWidth = texts.mapIt(it.stringWidth).max
for text in texts:
  let diff = maxStringWidth - text.stringWidth
  let pad = " ".repeat(diff)
  echo "| " & text & pad & " |"

このコードを実行したときの結果は以下のとおりです。

実行結果

最後の実行結果以外は文字幅について考慮していないため、 日本語が混在すると罫線の位置がずれていることがわかります。

絵文字の例

絵文字は少し特殊です。 EastAsianWidthでは絵文字はNeutralに属しており、1文字分として扱われます。

しかしながら、ほとんどのソフトは絵文字を2文字分として扱っています。 なので、絵文字はNeutralであるけれど、文字幅としては2文字を返すようにする必要がありました。 絵文字コード範囲だけ特別扱いするようにして、2文字幅を返すように実装しました。

以下に文字幅のテストコードを転記します。

import eastasianwidth

doAssert "☀☁☂☃".stringWidth == 8
doAssert "🧀".stringWidth == 2

ライブラリの使い方

インストール

インストールには以下のコマンドを実行します。

nimble install eastasianwidth

プロジェクトとして使用する場合は、 Nimbleファイルに記述する以下の設定を記述します。

requires "eastasianwidth >= 1.1.0"

使い方は前述の問題になる例を参考にしてください。

また、rectというツールで 実際に僕は今回作成したeastasianwidthライブラリを使用しています。 このrectについてはいずれ記事にしようと思います。

まとめ

自作のライブラリeastasianwidthについて説明しました。

仕組みは結構単純なので実装にはそこまで苦労しませんでした。 他の言語に移植するのも容易だと思います。

今後別言語で同様の問題に遭遇したときは移植しようかなぁと思います。

NimでPNM画像を扱うライブラリを書いた

NimでPNM画像を扱うライブラリを書きました。

リポジトリは下記の通りです。

github.com

Qiita - Nimのパッケージリポジトリに自前のライブラリを追加する流れの手順を実施して すでにnimble install可能な状態です。

Qiitaにも書いたのですが 自作のライブラリなのでブログに載っけといたほうがいいようなのでブログに転記しました。

そもそもNimって?

Qiita - 至高の言語、Nimを始めるエンジニアへにNimとは何かが書かれています。 僕の感触としてはPythonの皮をかぶったRubyっぽいC言語です。

開発環境

  • Ubuntu18.10
  • Nim 0.19.4

PNMとは

以下のWikiに書かれている内容がわかりやすいです。

PNM (画像フォーマット) - Wikipedia

一応説明すると、2次元の数値の並びがそのまま画像として表示される画像フォーマットになります。

たとえば以下のテキストはPNMの1つです。

P1
5 5
0 0 1 0 0
0 1 1 0 0
0 0 1 0 0
0 0 1 0 0
0 1 1 1 0

これを画像ビューワで開くと、以下のようにレンダリングされます。

t.png

前述のテキストファイルは以下のような書式になっています。

  • 1行目に画像フォーマット名
  • 2行目に列数、行数
  • 3行目以降に画像のデータ

データ部分については、0が白色、1が黒色としてレンダリングされます。 PNMはテキストファイルだけ渡されても自力で脳内レンダリングしやすいフォーマットです。

前述の P1 というディスクリプタの画像は PBM という画像フォーマットになります。 PNM(Portable Anymap)は1つの画像フォーマットではなく、PBM、PGM, PPMの総称です。

PNMの画像フォーマットはWikiにも記載あるとおり6種類あります。

ディスクリプタ データフォーマット
P1 PBM (テキスト)
P2 PGM (テキスト)
P3 PPM (テキスト)
P4 PBM (バイナリ)
P5 PGM (バイナリ)
P6 PPM (バイナリ)

今回作成したpnmというライブラリでは、この6種類すべて扱えるように実装しました。

PBMの実装

PBM、PGM、PPMと書式があって、どれも簡単なフォーマットだったので実装には苦労しませんでした。 そのうち、一番めんどくさかったのは、PBM(P4)です。

バイナリ形式なのですが、バイナリデータのビットがそれぞれ画像のドットに対応するので 0, 1の数値データを8個ずつ切り出して1byteのデータに変換する必要がありました。

せっかくなので、この記事では一番面倒だったPBMの書き込みについてを取り扱います。

ライブラリの使い方

pnmライブラリを使ってPBM P4として画像出力するコード例をいかに示します。

import pnm

let col = 5
let row = 5
let data = @[
  0'u8, 0, 1, 0, 0,
  0,    1, 1, 0, 0,
  0,    0, 1, 0, 0,
  0,    0, 1, 0, 0,
  0,    1, 1, 1, 0,
]
let pbm = newPBM(pbmFileDiscriptorP4, col, row, data.toBin(5))
writePBMFile("1.pbm", pbm)

このコードを実行すると、前述のPNM画像ファイルが生成されます。

2進数のデータをbyteデータに変換する

dataは5行5列のデータです。 25個のデータですが、これをbyteデータに変換します。 期待値としては、以下のようなbyteデータにします。

0b0010_0000
0b0110_0000
0b0010_0000
0b0010_0000
0b0111_0000

newPBM(pbmFileDiscriptorP4, col, row, data.toBin(5)) でのtoBinはbyteデータへの変換をやっています。

5データずつ切り出して5bitのデータにする必要がありますが byteデータは8bitです。 byte型にするには3bit分たりないのですが、足りない分は左シフトします。

toBinは今回作成したライブラリのサブモジュール内のプロシージャの1つです。 toBinプロシージャの実装をいかに示します。

proc toBin*(arr: openArray[uint8], col: int =  8): seq[uint8] =
  ## Returns sequences that binary sequence is converted to uint8 every 8 bits.
  runnableExamples:
    doAssert @[1'u8, 1, 1, 1, 0, 0, 0, 0].toBin == @[0b1111_0000'u8]
    doAssert @[1'u8, 1, 1, 1, 1, 1].toBin == @[0b1111_1100'u8]
    var s: seq[uint8]
    doAssert s.toBin == s
  var data: uint8
  var i = 0
  for u in arr:
    data = data shl 1
    data += u
    i.inc
    if i mod 8 == 0:
      result.add data
      data = 0'u8
      continue
    if i mod col == 0:
      data = data shl (8 - (i mod 8))
      result.add data
      data = 0'u8
      i = 0
  if data != 0:
    result.add data shl (8 - (i mod 8))

arrから1つずつデータを取り出して加算して左シフトを繰り返し、 1byte分データが加算されたらresultに追加を繰り返すような実装です。

Nimでは##をプロシージャ内に書くとドキュメンテーションコメントとして扱われます。 ライブラリとして公開するためにドキュメントも必要と思ったので書いています。

runnableExamplesドキュメンテーションコメントの1つです。 nim docでドキュメントを生成する際に、runnableExamplesのブロックのコードを実際にコンパイルして実行して コードが実行可能であることを検証してくれます。また、このブロックにかかれているコードもドキュメントに含まれます。

このソースコードから以下のドキュメントが生成されます。 https://jiro4989.github.io/pnm/util.html#toBin%2CopenArray%5Buint8%5D%2Cint

ファイル出力

writePBMFileではnewPBM()で生成した構造体をbyteデータに変換してファイル出力します。 byteデータへの変換は以下のような実装になっています。 データ構造は単純で、それぞれのデータをuint8型に変換しているだけです。

proc formatP4*(self: PBM): seq[uint8] =
  ## Return formatted byte data for PBM P4.
  runnableExamples:
    let p4 = newPBM(pbmFileDiscriptorP4, 1, 1, @[0b1000_0000'u8])
    doAssert p4.formatP4 == @[
      'P'.uint8, '4'.uint8, '\n'.uint8,
      '1'.uint8, ' '.uint8, '1'.uint8, '\n'.uint8,
      0b10000000'u8,
    ]
  # header part
  # -----------
  # file discriptor
  result.add self.fileDiscriptor.mapIt(it.uint8)
  result.add '\n'.uint8
  # col and row
  result.add self.col.`$`.mapIt(it.uint8)
  result.add ' '.uint8
  result.add self.row.`$`.mapIt(it.uint8)
  result.add '\n'.uint8
  # data part
  # ---------
  result.add self.data

書き込みをしている箇所はこれだけ。特に凝ったことはしていません。

let bin = data.formatP4
discard f.writeBytes(bin, 0, bin.len)

まとめ

PNMを扱うためのライブラリの使い方と、その実装の一部について説明しました。

PNMはPNGなどの一般的な画像フォーマットと比べると、非常に簡単な書式なので、実装の練習としては有用です。 僕の場合は、ビット演算を今までほとんどやったことなかったのですが、PBM P4の実装を通してビット演算の理解が深まりました。

あと実装についてですが、メソッドチェーンで処理をどんどんつないで コードをかけるのが面白いな、と感じました。

特にsequtilsstrutilsのモジュールには強力なものがたくさんあるので 少ないコード量でスイスイ実装を進められたと感じています。 また、スライスの値比較とかも普通に==でできますし、構造体のポインタ型のデータの値比較も 変数名の後に[]と書くだけで値型として扱えるのでテストコードも書きやすいです。

コード量はテストコード込で以下のようになりました。

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Nim                              4            105            402           1075
-------------------------------------------------------------------------------
TOTAL                            4            105            402           1075
-------------------------------------------------------------------------------

しかしながら、後からコードを見直したときに、1行の情報量が増えやすく 気を抜くとすぐに可読性が低下しそうな危うさも感じました。 普段良く使ってるGoと比べると可読性は低くなりやすいと感じます。

以上です。

Terminal上の色のついたテキストを画像に再現するコマンド(textimg)をGoで作った

Terminal上の色のついたテキストを画像に再現するtextimgというコマンドをGoで作りました。 なぜ作ったのか、と何ができるのか、について記載します。

リポジトリは下記。

github.com

なぜ作ったのか

シェル芸bot環境で色付きのテキストを画像に再現したかったからです。 シェル芸bot環境にはImageMagickがインストールされています。 また、テキストを画像に出力する処理を簡易にするためのimgoutというコマンドもあります。

ImageMagickで色のついたテキストを画像に変換するには、非常に複雑な オプションを組み合わせる必要があって、Twitterの文字数内では辛いものがあります。

Linux環境でテキストに色をつけるにはエスケープシーケンスを使用します。 色のついたテキストを出力するコマンドもいくつかあって それをそのまま画像に起こせたら楽しいかな、と考えたからです。

使い方

非常に単純な使用例は下記のとおりです。

textimg $'\x1b[31mRED\x1b[0m' -o out.png

red

より複雑な使用例は下記のとおりです。

seq 0 255 | while read -r i; do
  echo -ne "\x1b[48;5;${i}m$(printf %03d $i)"
  if [ $(((i+1) % 16)) -eq 0 ]; then
    echo
  fi
done | textimg -o 256_bg.png

bgall
アニメーションGIFにも対応しています。 シェル芸bot環境での使用例は以下です。

使用しているコマンドのオプションの説明は以下のとおりです。

textimg -sal8 -d 6 -F 4

  • -s シェル芸botの画像出力先ディレクトリに画像を保存する(/images/t.gif)
  • -a アニメーションGIFとして画像を生成する
  • -l 8 1フレームの画像に何行テキストを使用するか
  • -d 6 アニメーションのフレームの待ちフレーム(delay)
  • -F 4 フォントサイズ

実装

エスケープシーケンスを含む文字列は以下のように分解・分類できる。

\x1b[1;31;42mRed foreground Green background\x[0mNormal

  • 分解後
    • \x1b[1;31;42m
      • 1 太字にする (文字装飾)
      • 31 文字色を赤にする (色変更)
      • 42 背景色を緑にする(色変更)
    • Red foreground Green background (文字列)
    • \x1b[0m 文字の装飾や色変更をもとに戻す (色変更)
    • Normal (文字列)

このように文字列をエスケープシーケンスか、テキストかに分解し、 エスケープシーケンスの中から着色に関係のある文字列か否かに分類している。

エスケープシーケンスとのマッチはそれぞれ以下の正規表現で取り出している。

  • 色系:^\x1b\[[\d;]*m
  • 色系以外:^\x1b\[\d*[A-HfSTJK]

画像描画では、文字列が来たときだけ画像変数にテキストを書き込み、それ以外の場合 は書き込むテキストに指定する色や装飾の変更だけを行うのをひたすら繰り返すように している。

前述の文字列の場合は以下のような順序で処理をしています。

  1. なにもしない(太字装飾は無視)
  2. foregroundColor = red
  3. backgroundColor = green
  4. drawText("Red foreground Green background", foregroundColor, backgroundColor)
  5. foregroundColor = defaultColor
  6. backgroundColor = defaultColor
  7. drawText("Normal", foregroundColor, backgroundColor)

※実装のイメージなので実際のコードの通りではないです(変数名とか)。

エスケープシーケンスなどの情報はBash tips: Colors and formatting (ANSI/VT100 Control sequences)を参考にした。

まとめ

Terminal上の色のついたテキストを画像に再現するtextimgというコマンドについて 説明しました。

シェル芸bot環境に色のついたテキストを画像として再現できるようになって とても満足しています。

シェル芸botを使ってる方からもそれなりに気に入っていただけたようで、 作って公開して少ししか経っていないのにスター数が一番多いリポジトリになりました。 やはりそれなりに需要のあるものだったんですね。

ひとまずPNG生成できるようになって、アニメーションGIFも作れるようになって ひとまず自分のほしかった機能はだいたい実装し終わりました。 アップデートは何かバグが見つかったときとか、PRが来た時だけを考えています。

以上です。

第41回 シェル芸勉強会振り返り

第41回シェル芸勉強会に参加した。初参加です。

まえがき

2019/4/27 (土)に「jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ, ハ,}{,イブ}{無,有}罪シェル芸勉強会」に参加してきたのでその振り返り。 この名称自体もシェル芸で[ブレース展開]という記法。これをechoしてみると以下のよう になる(※長すぎたので一部抜粋)。

echo jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ,ハ,}{,イブ}{無,有}罪シェル芸勉強会"\n" | wc -l

865

echo jus共催 第41回{ウン,ガク,}{チ,ト,}{,ン}{,コイン}{ブ,}{ラブラ,ハ,}{,イブ}{無,有}罪シェル芸勉強会"\n" | head

jus共催 第41回ウンチブラブラ無罪シェル芸勉強会
第41回ウンチブラブラ有罪シェル芸勉強会
第41回ウンチブラブライブ無罪シェル芸勉強会
第41回ウンチブラブライブ有罪シェル芸勉強会 +第41回ウンチブハ無罪シェル芸勉強会
第41回ウンチブハ有罪シェル芸勉強会
第41回ウンチブハイブ無罪シェル芸勉強会
第41回ウンチブハイブ有罪シェル芸勉強会
第41回ウンチブ無罪シェル芸勉強会
第41回ウンチブ有罪シェル芸勉強会

シェル芸勉強会の様子は Togetterにまとまっています。

午前の部

  • 文字コードの話
  • 文字列の結合、絵文字の結合、絵文字の色の変更ができる
  • UnicodeData.txtというファイルにユニコード文字のすべてが載っている

午後の部

8問のシェルの問題を片っ端からとくというもの。 問題に必要なファイルはこちらにある。 シェル芸のコマンドを実際に実行するなら、 あらかじめ以下のコマンドを実行して準備を整えておく。

git clone https://github.com/ryuichiueda/ShellGeiData
cd ShellGeiData/vol.41

問題の一覧はこちら。 以降は問題と自分の回答。

Q1

Q.次のファイルについて、2列目をキーにしてエクセルの横列の記号(A, B, ..., Z, AA, AB, ...のやつ)順に並べ替えてください。

$ cat excel
114514 B
1192296 AA
593195 CEZ
4120 TZ
999 QQQ

回答としては、以下のように出力されてほしい。テストの意図としては、文字列の長さも 考慮してソートしてほしい、というもの。

114514 B
1192296 AA
4120 TZ
593195 CEZ
999 QQQ

普通に sort コマンドで2カラム目を指定すると以下のようにソートされてしまう。

% sort -k2 excel 
593195 AA
114514 B
1192296 CEZ
999 QQQ
4120 TZ

文字列の長さのカラムを追加してソートするのが正攻法だろう。 僕の回答としては以下の通り。

% awk '{print $0, length($2)}' excel | sort -k3 -k2 | cut -d ' ' -f 1,2 
114514 B
593195 AA
4120 TZ
1192296 CEZ
999 QQQ

Q2

Q.次のファイルのレコードを干支順にソートしてください。

$ cat eto_yomi
申 さる
子 ね
寅 とら
卯 う
巳 み
辰 たつ
丑 うし
酉 とり
戌 いぬ
亥 い
午 うま
未 ひつじ

ただし、次のファイルを補助に使って良いこととします。

$ cat eto
子丑寅卯辰巳午未申酉戌亥

etoファイルの並びを利用してeto_yomiをソートするもの。まずは正攻法から。

sortなので素直にsortコマンドと別のファイルの中身を結合すると考えてjoinコマンドを 使用する。僕の回答としては以下の通り。

% grep -o . eto | nl | sort -k2 | join -1 2 -2 1 - <(sort eto_yomi) | sort -nk2 | cut -d ' ' -f 1,3
子 ね
丑 うし
寅 とら
卯 う
辰 たつ
巳 み
午 うま
未 ひつじ
申 さる
酉 とり
戌 いぬ

流れとしては下記の通り。

  1. grep -o で1行のデータを縦に並べて nl で番号の列を追加
  2. 後に控えている join は結合するフィールドが辞書順にソートされている必要がある ため、joinに指定するフィールドを辞書順にソート
  3. joinで結合。 -1 2-2 1 で1個めのファイルの2フィールド目と2個めのファ イルの1フィールド目を結合する
    1. eto_yomiも辞書順でソート
  4. 最初にnlで付与した番号を使い干支順にソートし直す
  5. cutで不要なフィールドの削除

シェル芸の非常に良いお題だったと思う。

次にgrepを使用した非常にコンパクトな例。初め僕は思いつかなかった。

% grep -o . eto | xargs -I@ grep @ eto_yomi
子 ね
丑 うし
寅 とら
卯 う
辰 たつ
巳 み
午 うま
未 ひつじ
申 さる
酉 とり
戌 いぬ
亥 い

すでに干支順でソートされているのでそのままgrepしてしまう、というもの。 こういうアプローチもあるのか、とまたシェル芸の知見が深まった。

Q3

Q.次のファイルのレコードを数字(第一フィールドの計算結果)が小さい順に並べてく ださい。

$ cat kim_calc
1+2+4 金正日
4*3 金正男
3-1-5 金日成
495/3 金正恩
0x1F 金正哲

これは割とすぐに思いついた。はじめは bc コマンドを使用していたが0x1fで失敗する のでbashの算術式を使用するようにしたら通った。 僕の回答としては下記の通り。

% cat kim_calc | while read -r e n; do echo $(($e)) $e $n; done | sort -nk1 | cut -d ' ' -f 2,3
3-1-5 金日成
1+2+4 金正日
4*3 金正男
0x1F 金正哲

Q4

Q.次のファイルはシフトJISのテキストですが、これを1) 辞書順、2) 数字の小さい順 、にソートしてください。出力もシフトJISとします。

$ cat sjis | nkf -g
Shift_JIS
$ cat sjis | nkf -wLux
123 ずんごるももう
31 こきたてひーひー
9 ほじぱんふんじこみ
2242 たまもとやろう

最初は試験の意図がわからなかったが、2つ結果を出力するだけでよかったらしい。 1の辞書順については下記の通り。

% cat sjis | nkf -wLux | sort
123 ずんごるももう
20 ほじぱんふんじこみ
2242 うえってきたかるとらまん
31 こきたてひーひー

2の数字の小さい順は手間が必要。このファイルの数値は全角数字なので数値ソートがで きない。なので修正してソートしてから復元する必要がある。僕の回答としては下記の通 り。

% cat sjis | nkf -wLux | sed 'y/1234567890/1234567890/' | sort -nk1 | sed 'y/1234567890/1234567890/'
20 ほじぱんふんじこみ
31 こきたてひーひー
123 ずんごるももう
2242 うえってきたかるとらまん

sedのyコマンドを使用して対応する数値を変換しているだけ。これも簡単な方だと思う。

Q5

Q.サイズの小さい順にソートしてください。

$ cat size 
2GB
1.2GB
40000MB
1000000000kB
0.4GB
410MB

はじめはsortのヒューマンリーダブルオプションでいけるか、と思ったがダメだった。

% cat size | sort --sort h
1000000000kB
410MB
40000MB
0.4GB
1.2GB
2GB

なんとキロバイト順、メガバイト順、ギガバイト順にソートされている。 仕方なくnumfmtで変換して元に戻した。

% cat size | tr -d B | tr k K | numfmt --from iec --to=none | paste - size | sort -nk1 | cut -f2
0.4GB
410MB
1.2GB
2GB
40000MB

Q6

Q.sleepと内部コマンドだけを使って次の数を小さい順にソートしてください。

$ cat nums
5.4
0.34
2.3
0.9
6

これも割とすぐ思いついた。 内部コマンドってなんだろうと思ったが help というコマンドを使えば分かる。 whileやforが使えたのと、非同期実行を使えば行ける。

% while read i; do (sleep $i; echo $i) & done < nums
0.34
0.9
2.3
5.4
6

Q7

Q.次のローマ数字をソートしてください。

$ cat roman
IV
XI
LXXXIX
IX
XLIII
XX
VIII

これは割と力づくだったが一応いけた。

% cat ShellGeiData/vol.41/roman \
| sed 's/IV/4 /g;s/XL/40 /g;s/IX/9 /g;s/I/1 /g;s/L/50 /g;s/X/10 /g;s/V/5 /g;s/ /+/g;s/+$//g;s/.*/echo $((&))/e' \
| paste - ShellGeiData/vol.41/roman \
| sort -nk1 \
| cut -f 2
IV
VIII
IX
XI
XX
XLIII
LXXXIX

numconvというコマンドの存在を他の方のシェルから知った。 それを使えば以下のように修正できる。

% cat roman | numconv | paste - roman | sort -nk1 | cut -f2
IV
VIII
IX
XI
XX
XLIII
LXXXIX

Q8

Q.次のファイルを辞書順にソートしてください。ただし、濁点がついているものが先に 来るようにしてください。できる人はワンライナー中で「かきくけこがぎぐげご」の文 字を使わないでください。

$ cat gagigugego 
かき氷
ぎ・おなら吸い込み隊
きつねうどん
ぐりこもりなが事件
きききりん
がきの使い
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ
例
がきの使い
かき氷
ぎ・おなら吸い込み隊
きききりん
きつねうどん
ぐりこもりなが事件
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ

これははじめどうしたら良いかわからなかったが、午前の部で話していた内容を使えばす ぐに解決できることがわかった。濁点文字を濁点なしの文字と濁点の結合文字に分割する ことでソート順序を変更するというもの。

% cat ShellGeiData/vol.41/gagigugego | uconv -x NFD | sort | uconv -x NFC
がきの使い
かき氷
ぎ・おなら吸い込み隊
きききりん
きつねうどん
ぐりこもりなが事件
くその役にも立たない
げんしりょく発電
ごりらいも
こじんてきにはクソ

LT会

まとめ

はじめてシェル芸勉強会に参加したけれど、新しい知見がいっぱいだった。 シェルはガリガリ普段から書いていたので、問題自体は割となんとかなった。 8問のうち7問は自力で解けた。解けなかったのはがぎぐげごのやつ。

何はともあれシェル芸勉強会、面白かった。 シェルはいろんな環境にあるし、ちょっとした作業をぱぱっと自動化できてやはり好きだし 今後も必要で有り続ける技術だと思うので、引き続き勉強は続けようと思う。

ただし100行を超えるような処理をシェルで書くのはやめよう。 素直に他の言語を使うべし(経験者は語る)。

以上。