2020年4月12日日曜日

Emacs batch mode と HTML解析

前提

  • たくさんあるhtmlファイルの加工、編集をしたい。
  • 環境はWindows 10.
  • Emacsは入ってます。バージョン26.3.
  • MSYS2も入っていてBash使用可能。
  • しかしPython等のお手軽スクリプト言語の実行環境は無し。MicrosoftのPowershellやその他スクリプト言語には不慣れ。

ということでEmacsのDOM処理用関数を使うワンライナーを書くことにしました。


例題

カレントディレクトリにある拡張子htmlのファイルを開いてid="my-content"をもつ要素だけを抽出し、テキスト化して拡張子.txtのファイルに保存する、というもの。

for f in *.html; do
/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs --batch $f --eval='(princ (dom-texts (dom-by-id (libxml-parse-html-region (point-min) (point-max)) "my-content") "\n"))' > $f.txt;
done
  • "/c/Users/${user}/local/emacs-26.3-x86_64/bin/emacs": Windows上のemacsコマンドのパス
  • "--batch": Emacsバッチモード。バッチモードの定義は下記参考ページに書いてある。大雑把には、普段「バッファ」や「ウィンドウ」を使用するEmacsの入出力関数(message, princなど)を標準入力や標準出力、標準エラー出力に結び付けて、非インタラクティブに処理を実行する。
  • "--batch"直後の$fは処理対象のhtmlファイルで、非インタラクティブなEmacsはこのファイルを開いてバッファに読み込む。
  • "--eval"の引数としてelispコードを渡す。この例ではhtmlを開いたバッファ全体を"libxml-parse-html-region"関数に渡してDOM化し、次のそのDOMから"my-content"というidをもつ要素を"dom-by-id"関数で選び、選ばれた要素を"dom-texts"関数に渡してテキスト部分を抽出して"princ"で出力している。どの関数もEmacs標準のものだから外部のelispは利用していない。

2015年6月28日日曜日

HPサーバーのSSACLI(Smart Storage Administrator CLI)

RHELやCentOSにインストールしてやって、RAIDの構成や物理ドライブの情報をコマンドで調査できる(Windowsでもできると思う)

# hpssacli

=> controller all show

Smart Array P222 in Slot 4                (sn: xxxxxxxxxxxxxxxx)

=> controller slot=4 logicaldrive all show

Smart Array P222 in Slot 4

   array A

      logicaldrive 1 (931.5 GB, RAID 1, OK)

=> controller slot=4 physicaldrive all show

Smart Array P222 in Slot 4

   array A

      physicaldrive 2I:1:1 (port 2I:box 1:bay 1, SAS, 1 TB, OK)
      physicaldrive 2I:1:2 (port 2I:box 1:bay 2, SAS, 1 TB, OK)

=> quit

とても便利。めったに使わないのでコマンドをすぐ忘れそう。

2015年5月7日木曜日

「先読み」と「後読み」の正規表現(lookahead assertion と lookbehind assertion)

「詳説 正規表現」で「先読み」、「後読み」と呼んでいる正規表現は英語でそれぞれ lookahead assertion, lookbehind assertion、まとめて lookaround assertion と呼ぶ。

$ echo 'Regex example:1234567890.' | perl -p -i -e 's/(?<=\d)(?=(\d{3})+(?!\d))/,/g'
Regex example:1,234,567,890.

2015年5月6日水曜日

Windows ローカルアカウントでログオンするとき「.\ユーザー名」が使える

ドメインに参加していた Windows 7 のPCにローカルアカウントで入りなおすとき、いつも "コンピューター名\ユーザー名" の形式で入力していた。コンピューター名をその都度調べて正確に入力しないといけないから面倒くさいと感じていたが、実は「.\ユーザー名」という形式にも対応しているのだった。

出力をクリップボードにリダイレクトする方法(clip, xclip)

Windows で作業をしていて初めて知った("clip"コマンド)。Linux/Unix の世界にも同様のコマンドがあった("xclip")。知ってよかった。

C:\Users\foo>date /T | clip

2015年2月22日日曜日

Fedora Live USB Creator: "vesamenu.c32: not a COM32R image"

Fedora 21 Workstation の ISO と liveusb-creator をダウンロードしてWindows 8.1 を使ってブータブルUSBを作ってみたものの、次のメッセージが出て起動しなかった。(BIOS環境の場合のみ。UEFIの場合は問題なかった)


vesamenu.c32: not a COM32R image
boot:

この症状は、USBの中にあるSYSLINUXの設定ファイル、具体的には /syslinux/syslinux.cfg をほんの少しだけ変更してあげれば治った。

変更前の /syslinux/syslinux.cfg:
default vesamenu.c32
timeout 100
...
変更後
default linux0
timeout 100
...

こちらに書いてあるように、プロンプトでTabキーを押してイメージの候補を表示する、という方法もある。が、キーボード押したくない場合には syslinux.cfg を編集すればよい。



2015年2月20日金曜日

netshコマンドを使ってWindowsファイアウォールのポートを開ける

netshというコマンドを使えばいい。

たとえば TCP/80 を開けたいなら、コマンドプロンプトを管理者として開いて

netsh advfirewall firewall add rule name="HTTP" dir=in action=allow protocol=TCP localport=80
を実行すればOK。

ここで、nameオプションは「ルールの名前」と呼べばよいだろうか。文脈に応じて分かりやすい文字列を指定すればよい。

Windows Server 2012と2008で動作確認した。

2014年4月20日日曜日

Emacs 24.3, DDSKK-15.1, Mac OS 10.6.8

前提

  • Mac OS X 10.6.8
  • Emacs 24.3 (emacsformacosx.com で配布されている)
  • make が使えること

作業

ddskk-15.1 をダウンロードして展開
$ cd ~/work
$ wget ftp://ftp.ring.gr.jp/pub/elisp/skk/maintrunk/ddskk-15.1.tar.gz
$ wget ftp://ftp.ring.gr.jp/pub/elisp/skk/maintrunk/ddskk-15.1.tar.gz.md5
$ md5 ddskk-15.1.tar.gz
MD5 (ddskk-15.1.tar.gz) = c33f335994b93ea91783bf5b42663f07
$ cat ddskk-15.1.tar.gz.md5 
MD5 (ddskk-15.1.tar.gz) = c33f335994b93ea91783bf5b42663f07
$ tar xzf ddskk-15.1.tar.gz
ddskk-15.1/SKK-CFG の内容を変更
;; (setq SKK_DATADIR "/Applications/Emacs.app/Contents/Resources/etc/skk")
;; (setq SKK_INFODIR "/Applications/Emacs.app/Contents/Resources/info")
;; (setq SKK_LISPDIR "/Applications/Emacs.app/Contents/Resources/site-lisp/skk")
;; (setq SKK_SET_JISYO t)
上記4行を有効にする。
(setq SKK_DATADIR "/Applications/Emacs.app/Contents/Resources/etc/skk")
(setq SKK_INFODIR "/Applications/Emacs.app/Contents/Resources/info")
(setq SKK_LISPDIR "/Applications/Emacs.app/Contents/Resources/site-lisp/skk")
(setq SKK_SET_JISYO t)
念のため make what-where でインストールパスを確認
$ cd ddskk-15.1
$ make what-where
emacs -batch -q -no-site-file -l SKK-MK -f SKK-MK-what-where
Loading subst-ksc...
Loading subst-gb2312...
Loading subst-big5...
Loading subst-jis...
Loading /Users/th/work/ddskk-15.1/SKK-CFG...

SKK modules:
  skk-viper, skk-emacs, ccc, cdb, context-skk, queue-m, skk-abbrev, skk-act, skk-annotation, skk-auto, skk-autoloads, skk-azik, skk-cdb, skk-comp, skk-cursor, skk-cus, skk-dcomp, skk-develop, skk-gadget, skk-hint, skk-inline, skk-isearch, skk-jisx0201, skk-jisyo-edit-mode, skk-kakasi, skk-kcode, skk-leim, skk-look, skk-macs, skk-num, skk-server-completion, skk-server, skk-show-mode, skk-sticky, skk-tankan, skk-tut, skk-vars, skk-version, skk, skk-study
  -> /Applications/Emacs.app/Contents/Resources/site-lisp/skk

SKK infos:
  skk.info
  -> /Applications/Emacs.app/Contents/Resources/info

SKK tutorials:
  SKK.tut, SKK.tut.E, NICOLA-SKK.tut, skk.xpm
  -> /Applications/Emacs.app/Contents/Resources/etc/skk
パスが「/Applications/Emacs.app/Contents」になっているので問題なし。
make install
$ sudo make install Emacs=/Applications/Emacs.app/Contents/MacOS/Emacs
ここで、Emacsの実行形式ファイルのパスを指定するのを忘れないように(忘れると、あとでEmacsからddskkを実行したときにエラーが出ます)。

以上。

2013年12月8日日曜日

bash の wait コマンド(shell builtin command)

今日まで存在を知らなかった。。。バックグラウンドプロセスが終了するまで待ち合わせするコマンド。

惰性で順次実行してたシェルスクリプトを手軽に並行実行できるようになって効率上がるかも。

環境
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
Copyright (C) 2007 Free Software Foundation, Inc.
$ help wait
wait: wait [n]
    Wait for the specified process and report its termination status.  If
    N is not given, all currently active child processes are waited for,
    and the return code is zero.  N may be a process ID or a job
    specification; if a job spec is given, all processes in the job's
    pipeline are waited for.
例1) wait なし
$ cat test.sh 
#!/bin/bash
date
(sleep 1; echo 'sleep 1') &
(sleep 2; echo 'sleep 2') &
(sleep 3; echo 'sleep 3') &
date

$ ./test.sh 
2013年 12月 8日 日曜日 23時03分12秒 JST
2013年 12月 8日 日曜日 23時03分12秒 JST
sleep 1
sleep 2
sleep 3
バックグラウンドプロセスの終了を待たずに2つ目の date コマンドが実行されて日時を出力。その後1、2、3秒ごとに echo の結果が。
例2) wait あり
$ cat test.sh 
#!/bin/bash
date
(sleep 1; echo 'sleep 1') &
(sleep 2; echo 'sleep 2') &
(sleep 3; echo 'sleep 3') &
wait
date
$ ./test.sh 
2013年 12月 8日 日曜日 23時06分58秒 JST
sleep 1
sleep 2
sleep 3
2013年 12月 8日 日曜日 23時07分01秒 JST
全バックグラウンドプロセスの実行&終了を待ってから2つ目の date コマンドが実行された。合計3秒待ったから3秒後の日時がプリントされた。

2013年11月5日火曜日

FUSEの例(archivemount で tgz をマウントしてみる)

とあるAndroidスマホの中を見ていたら、ディレクトリの一部が「fuse」という謎のファイルシステムを使っていることに気がついた。初耳だったので調べてみると、LUKSをもっと手軽にしたようなものらしい(FUSEとLUKSを比較している記事がいくつかみつかった)。

ネットで紹介されているFUSEの利用例はたいていリモートホストのファイルをセキュアにSSHFSとしてマウントするものなので、ここでは矮小というか卑近というか要するにあまり役に立たない例としてローカルホストにあるアーカイブ(tgz)を読み書きする例にした。


1. 環境
Fedora release 19 (Schrödinger’s Cat)
ただし、「archivemount」というパッケージを yum でインストールした。
2. rootで、何でもいいからテキストファイルをつくってアーカイブ化(ファイル名:/root/work.tgz)
[root@localhost ~]# cd
[root@localhost ~]# mkdir work; for i in foo bar baz; do echo $i > work/$i.txt; done
[root@localhost ~]# ll work; cat work/*
total 12
-rw-r--r--. 1 root root 4 Nov  5 01:43 bar.txt
-rw-r--r--. 1 root root 4 Nov  5 01:43 baz.txt
-rw-r--r--. 1 root root 4 Nov  5 01:43 foo.txt
bar
baz
foo
[root@localhost ~]# tar cvzf work.tgz work/
work/
work/bar.txt
work/baz.txt
work/foo.txt
3. 共有用として /var/local/ の下に fuse というディレクトリを作り、/etc/fstab にマウントの設定を追加。
[root@localhost ~]# mkdir -p /var/local/fuse
[root@localhost ~]# cp /etc/fstab{,.orig}
[root@localhost ~]# echo '/root/work.tgz /var/local/fuse fuse.archivemount defaults,allow_other' >> /etc/fstab
この fstab のポイントは、ファイルシステムのタイプを「fuse.archivemount」にすることとオプションに「allow_other」を加えることの二点。
4. fstab の設定にしたがって mount してみる('-a'オプション)
[root@localhost ~]# mount -a
5. マウントされた内容を df と ls で確認
[root@localhost ~]# df
Filesystem               1K-blocks    Used  Available Use% Mounted on
/dev/mapper/fedora-root   28244124 9058868   17743876  34% /
devtmpfs                   1015516       0    1015516   0% /dev
tmpfs                      1022324     148    1022176   1% /dev/shm
tmpfs                      1022324     964    1021360   1% /run
tmpfs                      1022324       0    1022324   0% /sys/fs/cgroup
tmpfs                      1022324    2664    1019660   1% /tmp
/dev/sda1                   487652   83857     378195  19% /boot
archivemount            1048576000       0 1048576000   0% /var/local/fuse
[root@localhost ~]# ll /var/local/fuse/work
total 0
-rw-r--r--. 0 root root 4 Nov  5 01:43 bar.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 baz.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 foo.txt
6. 一般ユーザー(ここでは u1 とする)で、マウントしたディレクトリに読み書きしてみる。
[u1@localhost ~]$ id
uid=1001(u1) gid=1001(u1) groups=1001(u1) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[u1@localhost ~]$ cd /var/local/fuse/work
[u1@localhost work]$ echo hoge > hoge.txt
[u1@localhost work]$ ll
total 0
-rw-r--r--. 0 root root 4 Nov  5 01:43 bar.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 baz.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 foo.txt
-rw-r--r--. 0 root root 5 Nov  5 01:44 hoge.txt
[u1@localhost work]$ vi bar.txt    # ファイル内の文字列「bar」を「bar2」と書き換えるだけ
[u1@localhost work]$ ll
total 0
-rw-r--r--. 0 root root 5 Nov  5 01:44 bar.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 baz.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 foo.txt
-rw-r--r--. 0 root root 5 Nov  5 01:44 hoge.txt
[u1@localhost work]$ rm baz.txt    # ファイルを削除
[u1@localhost work]$ ll
total 0
-rw-r--r--. 0 root root 5 Nov  5 01:44 bar.txt
-rw-r--r--. 0 root root 4 Nov  5 01:43 foo.txt
-rw-r--r--. 0 root root 5 Nov  5 01:44 hoge.txt
7. アンマウントして、アーカイブの中身が変更されているか確認
[root@localhost ~]# umount /var/local/fuse
umount: /var/local/fuse: target is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
[u1@localhost work]$ cd    # u1 の存在で umount が失敗したので cd する
[root@localhost ~]# umount /var/local/fuse
[root@localhost ~]# mv work{,.orig}    # もともとのアーカイブをリネーム
[root@localhost ~]# tar xf work.tgz    # fuse.archivemount 経由で変更したアーカイブを展開
[root@localhost ~]# diff -uwbr work.orig work    # diff をとってみる
diff -uwbr work.orig/bar.txt work/bar.txt
--- work.orig/bar.txt 2013-11-05 01:43:39.096153269 +0900
+++ work/bar.txt 2013-11-05 01:44:38.000000000 +0900
@@ -1 +1 @@
-bar
+bar2
Only in work.orig: baz.txt
Only in work: hoge.txt
差分は期待どおり。これでOK.

2013年10月26日土曜日

bashでタブの出力:echo と printf

echo
$ echo -e "foo\tbar"
foo bar
printf
$ printf "foo\tbar\n"
foo bar

ただし、環境によっては echo の '-e' オプションが使えないとの意見あり(シェルの仕様に依存する)。

2013年9月19日木曜日

bash の brace expansion で数列生成できる

中括弧(brace)を使ったイディオム、たとえば

$ cp /foo/bar{,.orig}
はよく使っていた。でも数列まで扱えるとは知らなかった。

数列を作るときは seq コマンドを使って

seq 1 10
などと打っていた。

これも間違いではないが、中括弧を使えば seq 無しで、すなわち、

{1..10}
と書けるのだった。おそらく中括弧を使ったほうがスッキリきれいに書ける場面が多いだろう(キーボードを打つ回数だけ比較したらあまり変わらないかもしれないが。。。)

この brace expansion で数列を作る具体例のほとんどは「LinuxTips 連番ファイルをコマンド一発で作成する」に書いてあるのであまり付記することは無い。強いて挙げるならば、増分(increment)も指定できる点。以下がその例。

$ echo {1..10..2}
1 3 5 7 9
$ echo {z..a..5}
z u p k f a



2013年9月16日月曜日

Linuxの仮想コンソール切り換え(VMware Fusionにて)

MacBook に VMware Fusion を入れ、ゲストOSに Linux を入れ、コンソールで作業している場合の話。


別のコンソールに切り替えようとすると大抵は間違ったキーを押してしまう。たとえばただ単に B や C の文字がぽつんと表示されておしまいである。これがMacでなければ Alt + F1(F2,...,F6) キーで間違うことはないのだが。。。


この環境で打つべき正しい組み合わせは次のとおり:

optionキー + fnキー + F1(F2,...,F6)


失敗の原因は「option」でなく「command」を押してしまうこと。Macのoptionキーにはよく見ると "alt" という文字も書いてあるので見れば分かるというのに。。。とはいうもののキーボードの表面などは滅多に見ないのだからしかたがない。

2013年2月9日土曜日

外付HDDにWindows 7でチェックディスク(chkdsk) --> メモリ消費すごい

システムドライブ以外のドライブに対して「不良セクターのスキャンと回復」を有効にしてエラーチェックつまり "chkdsk /r" コマンドを実行するとメモリを大量に消費する。


What we do with a bug report? - Engineering Windows 7 - Site Home - MSDN Blogs


うちの Windows7(RAM 12GB搭載)でも確かに再現。2TBの外付けハードディスクドライブに対して chkdsk /r を実行し、しばらくするとメモリ使用量が8GB近く、システム全体で10GBほどに上がった。ここまで上がるとある意味楽しい。そして一晩寝かすと途中で強制終了されていた。

しかたないのでVMに入っている Windows Server 2008 で同じ chkdsk /r を試してみたら、問題は起こらなかった。

2013年1月27日日曜日

psコマンドの結果をgrepするときのtips

こじんまりした話題だが、、、grepコマンド自身がプロセスのリストに表示されるのがわずらわしいとき、いちいち「grep -v grep」を通してた。これは正規表現を使って簡潔にできる。

tips適用前
ps aux | grep mingetty | grep -v grep
適用例1
ps aux | grep mingett[y]
適用例2
ps aux | grep [m]ingetty

昔から脈々と受け継がれているらしい。2006年にはブログに書いている人がいるから。

ちなみに自分の場合は「プロのためのLinuxシステム・10年効く技術」という本で知りました。

2012年12月2日日曜日

「日経BP ITPro 今日の腕試し!」地味だけど面白い

ブログ停滞した。軽く書く。

大変失礼なこと書きますが、あか抜けない印象の ITPro のページ。「今日の腕試し!

なぜこのページにたどり着いたのかよく覚えてないけど、とにかくプラットフォーム、レイヤーを問わず雑多な問題が提供されていて面白かった。なぜか微笑がこぼれた。週に一回くらい見てもよいんじゃなかろうか。

2012年10月3日水曜日

ファイバチャネルHDDの40ピンコネクタ

拾い読みしてまとめた。

  • FC-HDDの、40ピンのコネクタはSCA-2に分類される。SCA-40と呼ばれることもある
  • 同じSCA-2で、80ピンのものもある。こちらはSCSI-HDDに用いられる
  • SCA(Single Connector Attachment)の目的の一つは、従来複数に分かれていたSCSIケーブルを1本にすること
  • 分かれていた、信号(68ピン)と電源等をまとめた結果 SCSI-HDD は80ピンになった。FC-HDDのほうは40ピンで済んだ
  • ケーブルが1本にまとまった結果、サーバーやSANストレージのディスク交換作業がちょっと楽になった(ちょっとした気遣いが大事ですよねー。USBコネクタの上下非対称問題とか考えると)

2012年9月14日金曜日

CentOS-6 で使われているTCPの輻輳制御アルゴリズム

/procを使って読み書きができた。CentOS-6(kernel 2.6.32-279)では"CUBIC"がデフォルトになっている模様。

# cat /proc/sys/net/ipv4/tcp_congestion_control
cubic

選択肢としては、"reno"もある。

# cat /proc/sys/net/ipv4/tcp_available_congestion_control
cubic reno