もう一人のY君

主にiPhoneのショートカットアプリのレシピやTipsなどを書いています. たまに数学の記事も書きます.

もう一人のY君 MENU  MENU

【iPhoneショートカット】指定ワードを含む行より下の複数行を取得する

Modified 2022/06/22

 先日の投稿を更に応用します.

 

 

ショートカット

ショートカット

  • Apple
  • 仕事効率化
  • 無料

※価格は記事執筆時のものです. 現在の価格はApp Storeから確認ください.

 レビュー時のiOSバージョン : iOS15.5

 

 

スポンサーリンク

 


 

 

 

テキストを操る

 ショートカットは他のアプリやPCソフトとのメリットやデメリットが露骨に異なる点がいくつかあります.

 例えばWebページからテキストを拾ってくるという操作をワンタップで行ってくれます.

 当然それで終わりではなく、他のアクションを使って加工ができます.

 

 

blog.thetheorier.com

 Yahoo!天気などのレシピは指定ページ結果のテキストを加工して編集したものです.

 

 しかしそのテキストから単純に10行目20行目…と拾っていくと、Yahoo!天気の場合であれば台風情報や地震速報といったイレギュラーな情報がページ先頭に現れる恐れがあり、その可能性があるとわかっている場合この方法は使えません.

 

 そのリスクを減らす手段の一つが、「指定ワードを含む行からテキストを取り出す」というアイデアです.

 必要な情報を取得するには、そのすぐ上の文字列から取り出すのがもっとも安心です.

 

 

blog.thetheorier.com

 先日紹介したのは指定ワードを含む行の「次の1行」でした.

 実際には一行では不十分で2行3行と欲しい場合もあります.

 実際Yahoo!天気の場合、ページを取得する際に気温などのデータがほぼすべて改行されてしまいます.

 なので改めて正規表現を使って少し書き換えます.

 

 

 

指定ワードを含む行より下の数行を取得する(基本)

 まず適当な文字の集まりを用意しておきます.

 

 

 マッチさせたい文字列と必要な行数を決めておきます.

 次行のみ取り出すときは「一致するテキスト」で

 

指定ワード.*\n.*

 

としていましたが、好きな行数を取得するために少し変更して、例えば指定ワードを含む行を含め5行分取得したい場合は

 

指定ワード.*(\n.*){5}

 

とします.

 括弧()はその中身をグループ化します.

 加えてその後ろに数字を括弧{}で囲めば、グループ化した文字列をその数の分だけ繰り返します.

 例えば(.){5}というのは.....と書くのと同じです.

 テキスト処理を行う上で何行欲しくなるかはその時その時で異なります. 「一致するテキスト」ではマジック変数が使えるためその繰り返し回数も自由に操作できます.

 

 

 このままだとマッチさせた行も含まれるので、「テキストを置き換え」アクションで「正規表現」をオンにした上で

 

^.*\n

 

を空に置き換えます.

 ^は行頭、.*は任意の文字列、\nは改行なので「1行目とその改行」にマッチします.

 

 

 これで指定ワードを含む行より後ろの複数行をまとめて取得できました.

 

 

指定ワードを含む行より下の数行を取得する(工夫)

 基本的には上で十分です、しかしものごとには例外が起こりうるものです.

 プログラムは例外がつきものです、個人で使うなど無視できる場合はほっとけばいいですがそうはいかないときもあります.

 

 例えば今回の場合、マッチする指定ワードが複数あったらどうしましょう?

 いやいやそもそもマッチしなかったら?

 

 …と、今回の場合単純に3通りの状況が起こり得ることが想像できます(後述しますが起こり得る問題がもう一つあります).

 実際上の例だと"12"、"34"を含む行が複数存在します.

 このまま使うと望んだ結果にならない可能性がでてきます.

 

 

 

 というわけで作り直してみます.

 前回同様適当な文字列を用意します.

 (今回はすでになっていますが)わざと重複する文字列を複数行に混ぜておきます.

 

 

 取得したい行数とマッチさせる文字列を指定します.

 今回は前者はレシピ内で固定、後者は「入力を要求」で実行時に入力させることにします.

 これはどんなレシピを作るかで変わってきます.

 

 次に適当な文字列の方に対して「一致するテキスト」で

 

.*指定入力.*

 

をマッチさせます.

 基本編ではこの時点で指定行数もまるごとマッチさせていましたが、マッチする数を確認するためまずはその行だけを確認します.

 そして「カウント」で上でマッチさせた数をカウントします.

 

 

 単純に結果を得るだけであれば上の正規表現は

指定入力.*

で十分です.

 しかしこれだと例えば123456という対象で45.*にマッチさせると123456でなく456を返します.

 マッチさせた行全体で何か行いたい場合は先頭にも.*を付ける必要があります.

 

 

 

 上で取得した、指定入力を含む行数で場合分けして処理します.

 まず行数が0の場合は「そもそも入力したワードがテキストにない」のでエラー処理となります.

 

 

 次に指定入力を含む行数が1の場合です.

 この時は基本編と同じ内容となります.

 「入力を要求」後に行った「一致するテキスト」に対してその行を含む行をマッチさせ、1行目を取り除きます.

 

 

 最後は指定入力を含む行が複数ある場合です.

 複数あるため「入力を要求」後に行った「一致するテキスト」の結果を「リストから選択」で一つ選ばせ、それに対して必要な行をマッチさせ、同じく1行目を取り除きます.

 

 …というのが基本ですが、指定入力を含む行があったとしても、その後ろに指定行数が存在しない可能性があります.

 「一致するテキスト」による正規表現のマッチでは、そのような場合結果が空になるため、if文でこの結果が空かどうかで場合分けすることでエラー処理を行います.

 

 これで今回は完了です.

 

 指定行数が足りなくとも、つまり1行でもあればよいという条件であれば、正規表現を(上の場合だと)

選択した項目(\n.*){1,数字}

と書き換えればOKです.
(正規表現のルールでは 選択した項目(\n.*){,数字} で良いはずなんですがエラーになります)

 

 

 

 実際に動かしてみます.

 マッチする行が複数ある場合はそのうち一つを選ばせてから処理が行われます.

 

 

 マッチした行を選んでもその下に欲しい分だけの行数がなかったり、そもそも入力したワードがどこにもない場合はエラーとなります.

 

 

 

 実際にはこのレシピそのものを作るメリットはありません.

 重要なのはここで紹介したアイデアそのものです.

 

 色々と応用してみてください.