Bashスクリプトの対話型マルチ選択

Bashスクリプトの対話型マルチ選択


ユーザーが出力ラインの1つを対話的に選択する簡単な方法はありますかlsblk -f

NAME    FSTYPE LABEL        MOUNTPOINT
sda                         
├─sda1  ntfs   WINRE_DRV    
├─sda2  vfat   SYSTEM_DRV   
├─sda3  vfat   LRS_ESP      
├─sda4                      
├─sda5  ntfs   Windows8_OS  /media/Win8
├─sda6  ntfs   Data        /media/Data
├─sda7  ext4   linux        /
├─sda8                      
├─sda9  ntfs   4gb-original 
├─sda10 ntfs   PBR_DRV      
└─sda11 ext4   home         /home

選択した行をスクリプトの連続で使用するために変数に入力しますか?

ユーザーが矢印キーを使用して行を上下に移動し、Enterキーを押して1つを選択できる場合は完璧だと思います。 (以前はインストール中にいくつかの設定スクリプトで見たようです。)これが可能でない場合、少なくともユーザーが使用するように選択する各行の前に数字をどのように取得できますかread

答え1

あなたが探しているdialogncursesさまざまなオプションを提供する非常に強力なツールです。マンページを注意深く読んでください。特に、次の--menuオプションが必要です。

   --menu text height width menu-height [ tag item ] ...
          As its name suggests, a menu box is a dialog  box  that  can  be
          used  to present a list of choices in the form of a menu for the
          user to choose.  Choices are displayed in the order given.  Each
          menu entry consists of a tag string and an item string.  The tag
          gives the entry a name to distinguish it from the other  entries
          in the menu.  The item is a short description of the option that
          the entry represents.  The user can move between  the  menu  en‐
          tries  by  pressing the cursor keys, the first letter of the tag
          as a hot-key, or the number keys 1-9. There are menu-height  en‐
          tries  displayed  in  the menu at one time, but the menu will be
          scrolled if there are more entries than that.

          On exit the tag of the chosen menu entry will be printed on dia‐
          log's  output.  If the "--help-button" option is given, the cor‐
          responding help text will be printed if  the  user  selects  the
          help button.

残念ながら、スペースを含むコマンドの出力を使用して合理的な方法で実装することは、さまざまな引用問題のためにかなり複雑です。とにかく、私はこれを行うことができず、使用する必要がありましたeval。それにもかかわらず、それは動作し、あなたが要求したことを行います。

#!/usr/bin/env bash
tmp=$(mktemp)
IFS=
eval dialog --menu \"Please choose a filesystem:\" 50 50 10 $(lsblk -f | sed -r 's/^/"/;s/$/" " "/' | tr $'\n' ' ') 2>$tmp
D=$(tr -d '│├└─' < $tmp | sed 's/^[ \t]*//' | cut -d' ' -f1)
printf "You chose:\n%s\n" "$D"

より移植性の高いアプローチのために、grepコマンドを次に変更します。

各出力行の周りに引用符(ダイアログボックスの「ラベル」など)と引用符で囲まれたスペース(ダイアログボックスの「アイテム」など)があるようにsed出力形式を指定し、改行文字をスペースとツリーの部分文字に置き換えます。lsblktr

結果は次のとおりです。

              ┌────────────────────────────────────────────────┐
              │ Please choose a filesystem:                    │  
              │ ┌────────────────────────────────────────────┐ │  
              │ │     NAME   FSTYPE LABEL MOUNTPOINT         │ │  
              │ │     sda                                    │ │  
              │ │     ├─sda1                                 │ │  
              │ │     ├─sda2                                 │ │  
              │ │     ├─sda3              /winblows          │ │  
              │ │     ├─sda4                                 │ │  
              │ │     ├─sda5                                 │ │  
              │ │     ├─sda6              /home              │ │  
              │ │     ├─sda7              /                  │ │  
              │ │     └─sda8              [SWAP]             │ │  
              │ └────↓(+)────────────────────────────90%─────┘ │  
              │                                                │  
              ├────────────────────────────────────────────────┤  
              │           <  OK  >      <Cancel>               │  
              └────────────────────────────────────────────────┘  

答え2

通常の操作では、カーソルの上の行を変更することはできません。すでにリフレッシュされたからです。あなたが見たスクリプトはおそらくcursesライブラリを使っているでしょう。したがって、本当にこれをしたい場合は、Pythonなどのスクリプト言語を使用し、そこでCursライブラリを使用することをお勧めします。

各行の前に数字を入れる方がはるかに簡単です。この awk 行を使用して、数字の前に数字を入れることができます。おそらくよりエレガントな方法があるかもしれませんが、これはうまくいきます。必要に応じて正規表現を変更します。

lsblk -f | awk 'BEGIN{disk=1;} /sd[a-z][1-9]+/ {print disk, ": ",$RT;disk=disk+1;next}{print "   ", $RT}'

関連情報