Tera Termマクロで複数行から任意の文字列を抽出【recvln】【strdim】

2023-01-04

タイトル画像_Tera Termマクロで複数行から任意の文字列を抽出する方法

この記事の目的

・Tera Termマクロの基本的な操作は一通り利用可能。
・showコマンド等、複数行のレスポンスから必要な文字列だけを抜き出し、別の処理に利用したい。

このような方向けに、Tera Termマクロの「recvln」と「strdim」コマンドを利用して実現する方法をまとめています。

「recvln」とは

recvlnは「recieve line」を意図したコマンドと推察されます。

Tera Termマクロのコマンドリファレンス(recvln)によると、文字通り「一行分の文字を受信する。」コマンドです。

recvln1回につき、受診した文字列一行分がシステム変数 「inputstr 」に格納されます。

以下にrecvlnの処理の図解を示します。

図解_recvln

ここでポイントとなるのは、recvlnで受信するのはあくまでも「一行分」の文字列であること。

例えばルーターでshowコマンドを打鍵した際には、基本的に数行から数十行に渡ってレスポンスが表示されます。

そこで普通にrecvlnを使おうとしても、recvln一行の記述につきレスポンス一行分しかinputstrとして取得できません。

これではrecvlnを数十行に渡ってrecvlnをマクロに羅列することになり、処理全般が煩雑で不便なものとなります。

そこで、次に紹介する「strdim」を組み合わせることで、より合理的で簡潔な記述が可能となります。

「strdim」とは

strdimは「strings dim」を意図したコマンドと推察されます。

stringsは文字列の意味です。

dimはプログラミング全般で配列や変数を宣言する際に使われます。元々は「dimension」を略したものです。

Tera Termマクロのコマンドリファレンス(strdim)によると、「指定した数の要素を持つ、文字列配列型の変数を宣言する。」コマンドです。

注:上記コマンドリファレンスの解説には「整数配列型」とありますが、これは誤植であると想定し、同ページの冒頭に記載の通り「文字列配列型」が正だとみなします。

strdimの記法

strdim [array] [size]

・array:配列の名前を宣言

・size:配列の要素の個数を宣言(※配列の添字は0から起算)

前項で言及しましたが、recvlnを使っても複数行のレスポンスから一行分しか受信できないことがネックでした。

このstrdimを利用し、showコマンドのレスポンス全行分を1行ずつ配列に格納することで、当初の目的を実現します。

以下にstrdimの処理の図解を示します。

strdimの処理

ここではshow ip routeのレスポンス3行分を格納するための配列として、「SIR[0]~SIR[2]」を作成しています。

任意の文字列を要素として収納可能な、空き箱を3箱用意するようなものとイメージしてください。

for文で全行分を配列に格納

次に、for文のループ処理を利用し、showコマンドのレスポンス全行分をstrdimで宣言した配列SIRに格納します。

以下の図解では、「for i 0 2」~「next」の4行で処理するマクロを示しています。

for文で全行分を配列に格納:実行前

ここではshow ip routeのレスポンスが3行だけなので、配列SIRの添え字はSIR[2]最大2です。

そのため、for文のカウンタ変数iの上限も2となります。

この変数iの上限はケースバイケース。もしレスポンスが10行であれば9となり、50行であれば49となります。

即ち前者は「for i 0 9」で後者は「for i 0 49」となり、変更箇所は最小限に留まります。

これはつまり、たとえレスポンスが何行であろうと臨機応変に対応できるということです。

次に、1ループ目の処理を以下に図示します。

for文で全行分を配列に格納:1ループ目開始

1ループ目では、for文で「i=0」のケースが処理されます。

recvlnで1行目のレスポンスを受信すると、暫定的にinputstrに格納されます。

その後、「SIR[0] = inputstr」とすることで、配列SIR[0]に恒久的に格納されます。

以下の図解は、1ループ目が完了した時点です。

for文で全行分を配列に格納_1ループ目完了

配列SIR[0]の中に、レスポンス1行目「C 192.168.1.0/24 is directly connected, Vlan10」が格納されました。

次に、2ループ目の処理を以下に図示します。

1ループ目と同様に、for文で「i=1」のケースが処理されます。

recvlnで2行目のレスポンスが配列SIR[1]に格納されます。

以下の図解は、2ループ目が完了した時点です。

配列SIR[1]の中に、レスポンス2行目「C 192.168.2.0/24 is directly connected, Vlan20」が格納されました。

ここまでの流れで既にご想像頂けたかと思われますが、念のため3ループ目の処理も以下に図示します。

3ループ目では、for文のカウンタ上限である「i=2」のケースが処理され、for文の処理は完了します。

recvlnで3行目のレスポンスが配列SIR[2]に格納されます。

最後に、3ループ目の完了時点を以下に図示します。

配列SIR[2]の中に、レスポンス1行目「S 192.168.3.0/24 [1/0] via 192.168.1.2」が格納されました。

これで全行分のレスポンスが配列SIRに格納された状態です。

配列に格納された要素の抽出

格納された要素からどれか一つを抽出するには、SIR[0]やSIR[1]などと配列の添え字で指定します。

一例として、SIR[3]の要素を「dispstr」コマンドでコンソールに表示するマクロを以下に図示します。

ここまでの一連の処理の後に「dispstr SIR[2]」をマクロ上で実行すると、SIR[2]に格納されている要素である、レスポンスの3行目がコンソールに表示されます。

配列SIRは文字列型変数なので、様々な形での処理が可能です。

例えば、以下の様な処理が想定されます。

  • 格納されたレスポンス行に対して、strmatchコマンドで正規表現によるパターンマッチングを行い、IPアドレスを抽出する。
  • 抽出したIPアドレスをstrconcatコマンドで任意の文字列と結合し、pingやルーティング設定を行う。

実際に必要となる処理に応じて、柔軟にご対応下さい。

もし行き詰まったら…

この記事では、Tera Termマクロで複数行のレスポンスから必要な文字列だけを抜き出す方法を解説しました。

ここまでの解説で、ご期待通りの処理は実現されましたでしょうか?

もし、この記事が一助になれたとしたら幸いです。

しかしながら、現場の業務要件やシステムは複雑で千差万別なもの。

どこかで見聞きした内容を、そっくりそのまま転用できるとは限りません。

それらしい情報をネットや書籍からかき集めて、思いつく限りの方法で散々試行錯誤したとしても、期待通りに動かず行き詰まったことはありませんか?

私も最初からスムーズに動かせたことは滅多に無く、トライアンドエラーを延々と繰り返してようやく形にできています。

では、何度試してもうまくいかず心が折れそうな時に、どうすれば最後まで諦めずに完遂できるのでしょうか?

そこで助けられたのが、以下の一冊。

「ですから、目標達成のために、まずするべきことは『意志力には限りがある』という事実を受け入れることです。」

-「やり抜く人の9つの習慣 コロンビア大学の成功の科学」第8章より引用-

この一文にはハッとさせられました。

本書によると、多くの人は自分の意志力を過大評価しており、「嫌なことから逃げて楽がしたい」という誘惑に自力で勝てると思い込んでいます。

確かに自分も、何かが上手くいかないと、いつの間にかテレビやネットやゲームに逃げていたことは数えきれないほどあります。

成功する人は、逃げ道や誘惑をなるべく排除することで、目標に集中できる「環境」を作る努力をしているのです。

本書で得た大きな知見は、意志力とは消耗することもあれば強化もできるため、その分コントロールも可能であるということ。

この概念が、目標に対する取り組み方をより楽にさせてくれました。

もし現在行き詰まっている方は、本書で何かしら打開のヒントを得ることが出来ます。

なお本記事に関するご質問やご意見等は、下記のコメント欄かTwitterのDMをご利用ください。