制御文字の検索と置換
背景
ブログのRSSで概要しか出していなかったところを全文出そうとしたら Input is not proper UTF-8, indicate encoding !
みたいに言われた。
おそらくどこかの記事で制御文字が含まれているのでなんとか見つけ出して撲滅したい。
やりかた
検索
git grep -IP '[[:cntrl:]](?<![\n\r\t])'
置換
find . -type f -name '*' | xargs perl -i -pe 's/[[:cntrl:]](?<![\\n\\r\\t])//g'
コマンドラインから直近の会議の zoom を開く
概要
在宅勤務となり、ほぼすべての会議が zoom となったが、Google Calendar から zoom を開くまでが色々とだるいので楽したい。
これまで
- Google Calendar を開き
- 予定の詳細を表示して
- zoomのURLをクリックすると
- 新しいタブが開き
- アプリケーションを開く許可を求められるので
- 「zoom.usを開く」
- タブを閉じる
参考:こんなページが表示される
これから
$ meeting Your next meeting is "会議その1", organized by silvers. It started 59 minutes ago. Calendar event URL: https://www.google.com/calendar/event?eid=xxxxxxxxxx Zoom URL: zoommtg://zoom.us/join?confno=xxxxxxxxxx Open Zoom? (y/N)n _____________________________________________________ Your next meeting is "会議その2", organized by silvers. It starts 17 seconds from now. Calendar event URL: https://www.google.com/calendar/event?eid=xxxxxxxxxx Zoom URL: zoommtg://zoom.us/join?confno=xxxxxxxxxx Open Zoom? (y/N)y
やりかた
1. zoom-go を入れる
流れに沿ってインストールして設定すれば zoom
で次の予定を表示させることができる。
問答無用で次の予定に参加するぞ!という感じであれば
$ zoom | grep zoommtg | cut -d ' ' -f 3 | xargs open
とかで十分。
複数会議が入り乱れているときとか意図せぬ会議を開いてしまいそうな人は次へ。
2. 対話的に開けるようにする
こんな感じのやつをPATHの通ったところに置く。 1個1個予定を表示しつつ、「これ開く?」って聞いてくれる。
2020/04/22 追記
5分前行動のせいで気付かなかったんだけど、最初の予定が5分以内なら自動で開始する機能があるっぽかったので、予定が連続していたり入り乱れていない場合以外は zoom
だけで十分かも。
https://github.com/benbalter/zoom-go/blob/d101021033af194490395637214d049833d02b92/zoom.go#L106-L114 https://github.com/benbalter/zoom-go/blob/c89e5ec469473c42998057efe49fbc450cf84bb8/cmd/zoom/main.go#L134-L143
draw.io で Alibaba Cloud のアイコンを使いたい
draw.io はVisioとの互換性高いので、 https://www.alibabacloud.com/help/doc-detail/67830.htm で配布されている Microsoft Visio template(.vssx) がそのまま使える。 ダウンロードしてドラッグすれば良い。
ScratchPadはブラウザのローカルストレージを使っているので永続化したければ、鉛筆のアイコンから Export してライブラリにしておくと良い(次回からは File > Open Library from
から開ける)*1。
Alibaba Cloud はじめるまで
次のISUCONでAlibaba Cloudを使うのでちょっと触ってみた。
プロダクトとサービス
たくさんあるけど今回はECS(Elastic Compute Service)を使う。
aliyun
管理画面でぽちぽちもできるけど、面倒なのでCLIを使う。 なんでaliyunなのかと思ったら、インターナショナルでは "Alibaba Cloud" という名前だけど、中国では "Aliyun / 阿里雲" というサービス名だかららしい。
RAM(Resource Access Management) > ユーザ > 管理 > AccessKey
からAccessKeyを作成して aliyun configure
で設定する。
$ aliyun configure Configuring profile 'default' ... Aliyun Access Key ID [None]: <Your AccessKey ID> Aliyun Access Key Secret [None]: <Your AccessKey Secret> Default Region Id [None]: ap-northeast-1 Default output format [json]: json Default Languate [zh|en]: en Configure Done!!! ..............888888888888888888888 ........=8888888888888888888D=.............. ...........88888888888888888888888 ..........D8888888888888888888888I........... .........,8888888888888ZI: ...........................=Z88D8888888888D.......... .........+88888888 ..........................................88888888D.......... .........+88888888 .......Welcome to use Alibaba Cloud.......O8888888D.......... .........+88888888 ............. ************* ..............O8888888D.......... .........+88888888 .... Command Line Interface(Reloaded) ....O8888888D.......... .........+88888888...........................................88888888D.......... ..........D888888888888DO+. ..........................?ND888888888888D.......... ...........O8888888888888888888888...........D8888888888888888888888=........... ............ .:D8888888888888888888.........78888888888888888888O ..............
aliyun
の使い方は --help
とか見ていけばだいたい使い方は分かる。
Linkでヘルプページが記載されているんだけど中国語なので、英語版のドキュメントは https://www.alibabacloud.com/help を見る。
$ aliyun ecs --help Alibaba Cloud Command Line Interface Version 3.0.24 Usage: aliyun Ecs <ApiName> --parameter1 value1 --parameter2 value2 ... Product: Ecs (Elastic Compute Service) Version: 2014-05-26 Link: https://help.aliyun.com/api/ecs Available Api List: ... ...
DescribeInstances
や DescribeSnapshots
とかで情報が見れるが結構帰ってくる json がでかいので jq
とかを使うのが吉。
Google Form送信時に情報をslackに通知をする
そういう機能が欲しかったのでGAS書いた。
手順
1. フォームを作る
適当に好きなフォームを作る。
2. スクリプトエディタからGASを書く
画面右上のメニューから選択する。
3. スクリプト書く
function onFormSubmit(e) { sendToSlack(e); } function sendToSlack(e) { var token = 'FIXME'; // your token var channel = 'FIXME'; // e.g. '#random' var username = 'FIXME'; var icon_emoji = 'FIXME'; // e.g. ':beer:' var payload = { 'token' : token, 'channel' : channel, 'text' : createText(e), 'username' : username, 'parse' : 'full', 'icon_emoji' : icon_emoji }; var params = { 'method' : 'post', 'payload' : payload }; var response = UrlFetchApp.fetch('https://slack.com/api/chat.postMessage', params); } function createText(e) { return '適当なメッセージ'; }
4. トリガを設定する
スクリプトエディタの時計みたいなところから以下のような感じでトリガを設定する。
投稿内容の取得例
Class FormResponse | Apps Script | Google Developers
投稿した人
var mail = e.response.getRespondentEmail(); var user = mail.split('@')[0];
もし会社とかでドメインが一緒なら@以前がおそらく社員の名前。
投稿内容
var res = e.response.getItemResponses(); var target = res[0].getResponse(); // 1個目の質問の回答 var comment = res[1].getResponse(); // 2個目の質問の回答
crontabでdateを扱うときとかに注意すること
45 9 * * 3 hoge.pl `date -v+2d +"%Y%m%d"`
こんな感じのことやろうとしたら
/bin/sh: -c: line 0: unexpected EOF while looking for matching ``' /bin/sh: -c: line 1: syntax error: unexpected end of file
こけてなんだろなーと思ったらcrontabでは %
以降を標準入力として扱うらしくエスケープが必要らしい。
みんながハマった道だと思いつつメモ残しておく。
Androidのパッケージ名に使える文字
AppStoreとあわせようとしてハマったのでメモ。
基本は英字。
先頭でなければ 数字と_
が使える。
private static String validateName(String name, boolean requireSeparator, boolean requireFilename) { final int N = name.length(); boolean hasSep = false; boolean front = true; for (int i=0; i<N; i++) { final char c = name.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { front = false; continue; } if (!front) { if ((c >= '0' && c <= '9') || c == '_') { continue; } } if (c == '.') { hasSep = true; front = true; continue; } return "bad character '" + c + "'"; } if (requireFilename && !FileUtils.isValidExtFilename(name)) { return "Invalid filename"; } return hasSep || !requireSeparator ? null : "must have at least one '.' separator"; }