FC2ブログ

本を読む

読書やコンピュータなどに関するメモ

「新仮面ライダーSPIRITS」20巻

こいつは「ヘルダイバー」

俺の道連れだ

 直球でZXのアクションが炸裂する巻。分身投影も決めたし。そして、崩壊する暗闇大使の魔方陣へ600km/hで突入。

 ほかのライダーの中で、われ先に飛び出すのが、昭和ライダーでもキャラの濃いアマゾンとストロンガーってのも、らしいね。

 しずか姉さんは、敵か味方かわからなくてミステリアスだなあ。

 巻末は、菅田俊さん対談PART II。身長があるので合う服がなくて自前の服とか、さらにバイクも自前とか、男前なエピソードが。

Bash 5.0の新機能:namerefの挙動の変更

Qiitaと同時投稿です

Bash 5.0では、namerefの名前解決で非互換の挙動があると言われています。

リリースアナウンスでは次のように書かれています。

There are a few incompatible changes between bash-4.4 and bash-5.0. The changes to how nameref variables are resolved means that some uses of namerefs will behave differently, though I have tried to minimize the compatibility issues.

「bash 5.0のNEWSファイル私訳」にも次のようにあります。

  1. 関数内でnamerefの名前解決のループは、グローバルスコープでの名前の変数 に解決されるようになりました。

そもそもnamerefを知らないと変更点もわからないので、順に説明します。

おさらい①:namerefって?

namarefはBash 4.3から導入された機能です。ksh由来のようで、AIXのマニュアルでは「名前参照」と、Solarisのマニュアルでは「nameref」と表記されているようです。

namerefは、ほかの変数を参照する変数を作る機能です。変数のエイリアス(別名)を付けるときなどに使います。

namerefはdeclare -nlocal -nなど、変数宣言のときに-nオプションを指定して作ります。namerefな変数に、ほかの変数名を文字列として代入すると、エイリアスのように動きます。

$ aaa=3                 # 変数aaaに3を代入
$ declare -n bbb        # namerefな変数bbbを宣言
$ bbb=aaa               # bbbに'aaa'を代入($aaaではない)
$ echo $bbb             # bbbの内容は?
3

おさらい②:namerefの使い道

namerefの使い道として自分が考えたのが、関数から関数に値を渡すときに、変数名を渡す方法です。

たとえば、関数から関数に配列を渡すときには、引数や標準入力ではそのままでは渡せません。そこでダイナミックスコープを使って渡す方法があります。

foo() {
  local ary=('a b' c d)         # 配列変数aryを宣言
  bar
}

bar() {
  echo ${ary[0]}                # fooで宣言された配列変数aryを参照
}

foo                             # 「a b」と表示される

ただbarから暗黙的に変数aryを参照するのがいまいちです。そこで、namerefを使って変数名を渡すことで、barではfooで宣言された変数名の知識が不要になります。

foo() {
  local ary=('a b' c d)
  bar ary               # “ary”という変数名を文字列で引数に
}

bar() {
  local -n var=$1       # nameref変数varに1つめの引数の文字列(変数名)を代入
  echo ${var[0]}
}

foo                      # 「a b」と表示される

namerefの挙動の違い

さて、Bash 5.0で挙動が変わったのはどのあたりでしょうか。

「関数内でのnamerefの名前解決のループ(A nameref name resolution loop in a function)」ということなので、namerefで循環参照を作ってみます。

aaa=7                           # グローバル変数aaa

foo() {
  local -n aaa                  # ローカルなnameref変数aaa
  aaa=aaa                       # aaaからaaa自身を参照
  echo $aaa
}

foo

これをBash 4.4で実行すると、循環参照の警告が表示されたあと、echo $aaaでは何も表示されません。

$ bash ./n.sh
./n.sh: line 6: warning: aaa: circular name reference

Bash 5.0で実行すると、循環参照の警告が表示されたあと、echo $aaaでグローバル変数aaaの値である「7」が表示されます。

$ ./bash ./n.sh
./n.sh: line 6: warning: aaa: circular name reference
7

結論

そもそも、Bashでnamerefをそれほど使うとは思わないし、その中でも特殊なケースなので、非互換による影響はほとんどないのではないでしょうか。

Bash 5.0の新機能:カーソルの画面行移動

Qiitaと同時投稿です

Bash 5.0のNEWSファイルをさくっと翻訳したエントリー「bash 5.0のNEWSファイル私訳」を先日書きました。

この中のReadline 8.0の新機能として、カーソルの画面行移動機能がありました。

b. キーに割り当てられるコマンドに新しく`next-screen-line' and
   `previous-screen-line'があります。カーソルを画面行のそれぞれ次と前
   の行の同じカラムに移動します。

さっそく試してみましょう。

Bash 5.0のコマンドラインから、Ctrl-↓にnext-screen-lineを割り当てます。

$ bind '"\e[1;5B": next-screen-line'

同様にCtrl-↑にprevious-screen-lineを割り当てます。

$ bind '"\e[1;5A": previous-screen-line'

コマンドラインで、1行が1画面行を超えるように文字を入力します。

$ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

ここでCtrl-↓とCtrl-↑を押すとカーソルが画面行を移動することがわかります。

Bash 5.0の新機能:localvar_inherit

Qiitaと同時投稿です

Bash 5.0のNEWSファイルをさくっと翻訳したエントリー「bash 5.0のNEWSファイル私訳」を先日書きました。

この中に、localvar_inheritという新しいshoptオプションが追加されたことが書かれています。

o. 新しいshoptオプション:localvar_inherit。設定すると、ローカル変数
   は、直前のスコープにある同じ名前の変数の値を継承します。

自分で訳しておいてなんですが、わかりにくいですね。

Bash 5.0のmanpageでは、こう説明されています。

localvar_inherit
        If set, local variables inherit the value and attributes
        of a variable of the same name that exists at a previous
        scope before any new value  is  assigned.   The  nameref
        attribute is not inherited.

やはりわかりにくいですね。

そこで、ちょこっと調べて試してみた結果を、順を追って説明します。

おさらい①:関数

多くのプログラミング言語と同じく、Bashでも関数を定義できます。定義した関数はコマンドとして実行できます。

$ cat hello.sh
hello() {               # helloという関数を定義
    echo hello
}

hello                   # helloを実行
$ bash ./hello.sh
hello

おさらい②:ローカル変数

単純なシェルでは変数はグローバル変数しかありません。しかしBashでは、localコマンドによって関数内のローカル変数を定義できます。

$ cat localvar.sh
foo() {
  local aaa     # aaaというローカル変数を定義
  aaa=5         # aaaに5を代入
}

aaa=3           # aaaに3を代入
foo             # fooを実行
echo $aaa       # その後でaaaの値は?
$ bash ./localvar.sh
3

おさらい③:ローカル変数はダイナミックスコープ

Bashのローカル変数のスコープは、呼び出し先の関数でも有効です。Common Lispのスペシャル変数や、Emacs Lispのデフォルトのダイナミックスコープ変数、Perlのlocalなどに似ています。

次のように、関数fooと、fooから呼び出す関数barを定義します。すると、fooで定義したローカル変数aaaがbarからも参照できます。

$ cat scope.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
}

bar() {
  echo $aaa     # barでのaaaの値は?
}

foo
$ bash ./scope.sh
3

同じ変数aaaを参照しているので、barで値を変更すると、fooでも変更されています。

$ cat scope2.sh
foo() {
  local aaa=3   # aaaというローカル変数を定義して値を3に
  bar
  echo $aaa     # barを呼び出した後でaaaの値は?
}

bar() {
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./scope2.sh
5

ようやく本題:localvar_inherit

では、Bash 5.0の新機能であるlocalvar_inheritを見てみましょう。

localvar_inheritをオンにすると、呼び出し元の変数と同じ名前の変数をlocalで定義したときに、呼び出し元の変数の値と属性が コピー されます。

次の例では、fooとbarで同じ名前の変数aaaを定義しています。barではaaaの値を代入していないのに、fooでaaaに設定した値が参照されます。

$ cat inherit.sh
shopt -s localvar_inherit       # localvar_inheritをオンに

foo() {
  local aaa=3   # fooでローカル変数aaaを定義
  bar
}

bar() {
  local aaa     # barでもaaaを定義。値は代入しない
  echo $aaa     # aaaの値は?
}

foo
$ bash ./inherit.sh
3

ダイナミックスコープと違い、同じ変数を参照するわけではありません。次のように、barでaaaの値を変更しても、fooのaaaの値は変わりません。

$ cat inherit.sh
shopt -s localvar_inherit

foo() {
  local aaa=3
  bar
  echo $aaa     # barを呼び出した後でaaaの値は?
}

bar() {
  local aaa
  aaa=5         # barでaaaに5を代入
}

foo
$ bash ./inherit.sh
3

用途

さて、これをどういうところで使うと便利でしょうか。

普通の変数の値であれば、引数などで渡せば十分です。ただし、配列は引数などでは渡しづらいので、localvar_inheritを使って呼び出し先にコピーするのが便利そうです。

bash 5.0のNEWSファイル私訳

Qiitaと同時投稿です

bash 5.0(とreadline 8.0)がリリースされたので、NEWSファイル(新機能リスト)からbash 5.0の新機能の部分を訳してみました。

「メルカリ 希代のスタートアップ、野心と焦りと挑戦の5年間」

 書店の平台で見て買ってみて、さくっと読んだ。メルカリの創業(それ以前も少し)から現在までの成長の軌跡を書いたビジネス書だ。メルカリのサービス自体の話の割合はあまり大きくなく、創業者である山田進太郎氏を中心に、その人脈から関与した人達の列伝と、経営面での活動が描かれている。

 私はノンフィクションとして面白く読んだけど、ビジネスのヒントを得ようとして読む人は、どのあたりに注目するんだろうか。

 細かいところでは、マス層への知名度を上げるためにTV CMを活用した話が印象に残った。同じ頃に「TV CMはネット広告のように精緻な測定ができないのが弱点」という話を読んだところだったので、効果測定に関係なくゼロからマス層を狙う場合はTV CMの効果が大きいのかなと。

 あと、本書でも海外事業に重きが置かれていると書かれているけど、今のところ好調とは言いがたいように見えるので、そのへんが企業としての今後の注目点かなと。

ターミナル用RSSリーダーのnewsbeuterを試す

 「RSSは死んだ」的なことが言われる昨今ですが、私はRSSリーダーを日々使っています。便利だと思うんですけどね。

 数百フィード以上を日常的にチェックするには、クラウド型のRSSリーダーが必須です。ただ、たとえばアドベントカレンダーなどで一時的にフィードをチェックするには、ローカルでシンプルなRSSリーダーを使うほうが小回りが効きます。

 Adventarで2018年のアドベントカレンダーを追いかけるのに、私はnewsbeuterを使ってみました。newsbeuterは、ターミナルのTUI(text user interface)画面で動作します。以下、Ubuntuデスクトップでの例です。

 インストールはaptから。

$ apt install newsbeuter

 まず一度newsbeuterを起動すると、エラーで終了します。このとき、設定ディレクトリ「~/.newsbeuter」が作られます。

$ newsbeuter
XDG: configuration directory '/home/emasaka/.config/newsbeuter' not accessible, using '/home/emasaka/.newsbeuter' instead.
Starting newsbeuter 2.9...
Loading configuration...done.
Opening cache...done.
Loading URLs from /home/emasaka/.newsbeuter/urls...done.
Error: no URLs configured. Please fill the file /home/emasaka/.newsbeuter/urls with RSS feed URLs or import an OPML file.

newsbeuter 2.9
usage: newsbeuter [-i <file>|-e] [-u <urlfile>] [-c <cachefile>] [-x <command> ...] [-h]
        -e              export OPML feed to stdout
        -r              refresh feeds on start
        -i <file>       import OPML file
        -u <urlfile>    read RSS feed URLs from <urlfile>
        -c <cachefile>  use <cachefile> as cache file
        -C <configfile> read configuration from <configfile>
        -X              clean up cache thoroughly
        -x <command>... execute list of commands
        -o              activate offline mode (only applies to The Old Reader synchronization mode)
        -q              quiet startup
        -v              get version information
        -l <loglevel>   write a log with a certain loglevel (valid values: 1 to 6)
        -d <logfile>    use <logfile> as output log file
        -E <file>       export list of read articles to <file>
        -I <file>       import list of read articles from <file>
        -h              this help

 購読するフィードは、「~/.newsbeuter/urls」というテキストファイルを新規作成して書き込みます。たとえばこんな感じで。

https://adventar.org/calendars/3599.rss
https://adventar.org/calendars/2877.rss
https://adventar.org/calendars/2940.rss

 ついでに設定を変更しておきます。設定は「~/.newsbeuter/config」というテキストファイルです。ここでは、メニュー画面で「j」「k」キーでも操作できるようにします(デフォルトでは「↓」「↑」キー)。

bind-key j next
bind-key k prev

 ここで改めてnewsbeuterを起動します。

$ newsbeuter

 すると、フィード一覧がTUIで表示されます。

フィード一覧

 「R」(「Shift」+「r」)キーで、フィードが更新され、新着がチェックされます。

フィードが更新された

 フィードのタイトルが取得されて表示されました。

 さきほど設定した「j」「k」キーにより、対象フィードを移動できます。「Enter」キーで、対象フィードに入り、エントリー一覧が表示されます。

エントリー一覧

 ここの操作もフィード一覧と同様です。未読のエントリーには「N」が付いて太字になっています。ここから「Enter」でエントリーの内容が表示されます。

エントリーが表示

 エントリーのリンク先は、「o」キーで表示できます。呼び出されるWebブラウザーは、UbuntuやDebianのデフォルトではsensible-browser(デフォルトのWebブラウザーを開くシェルスクリプト)、本家ソースのデフォルトではlynxです。このWebブラウザーも「~/.newsbeuter/config」で設定できます。

 エントリー表示から元に戻るのは「q」キーです。エントリー一覧やフィード一覧からも「q」キーで戻れます。

 以上、単なる“動かしてみましたエントリー”でした。

«  | HOME |  »

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly


FC2Ad