2017-02-25 33 views
1

目的:docker psの対話型バージョンを作成しようとしています。が存在することになるBASH - 特殊文字を含む文字列を解析する

CONTAINER ID  IMAGE    COMMAND     CREATED    STATUS    PORTS         NAMES 
1. bf4a9c7de6bf  app_1    "docker-php-entryp..." 7 days ago   Up About an hour 443/tcp, 0.0.0.0:80->80/tcp, 9000/tcp app_1 
2. 26195f0764ce  app_2    "sh /var/www/html/..." 10 days ago   Up About an hour 443/tcp, 127.0.0.1:8000->80/tcp   app_2 

(1/2等)を選択すると:

例など、SSH、停止、開始:基本的に、それぞれの行は、ユーザーができるような「メニュー」であるましたオプションメニューを使用して、選択したコンテナに対してさまざまなアクションを実行します。

問題:docker psコマンドの各行を解析して、コンテナIDと他の値を配列要素として持つようにする方法を見つけられないようです。

これまでコード:

list=`docker ps` 
IFS=$'\n' array=($list) 

for index in ${!array[@]} 
do 
    declare -a 'a=('"${array[index]}"')' 
    printf "%s\n" "${a[@]}" 
done 

結果:

あなたが引用していくつかの問題を持っているように見えます
CONTAINER 
ID 
IMAGE 
COMMAND 
CREATED 
STATUS 
PORTS 
NAMES 
/usr/bin/dockersh: array assign: line 9: syntax error near unexpected token `>' 
/usr/bin/dockersh: array assign: line 9: `bf4a9c7de6bf  app_1    "docker-php-entryp..." 7 days ago   Up About an hour 443/tcp, 0.0.0.0:80->80/tcp, 9000/tcp app_1' 
+0

私はループ内で宣言をするのは混乱していますか?常に 'a'配列の場合は、なぜそれを複数回宣言しますか?また、データを見ることなく(私はドッカーをインストールしていない他のものと同様に)、それは提供するための良い答えを知ることを難しくしますか? – grail

+0

ご覧ください:http://www.shellcheck.net/ – Cyrus

+0

@grail - データは私の質問のExampleブロックに表示されています。宣言文に関しては、私は2つの配列を扱っていると考えました: 1。行の配列 2.各行の "列"の配列 – aniculescu

答えて

1

あなたは、行/列内のアクセス可能なすべてのあなたのdocker psフィールドを持つ行列を特徴と連想配列を持っているしたい場合は、フィールド間の区切り|を挿入するためにawkを使用することができます。その後、単一の連想配列で結果をエクスポートします(例:7)期待していた列の数に応じて行列を構築する:awk一部で

#!/bin/bash 
IFS=$'|' 

data=$(docker ps -a | awk ' 
function rtrim(s) { sub(/[ \t\r\n]+$/, "", s); return s } 
{ 
    if (NR == 1) { 
     head[1] = index($0,"CONTAINER ID") 
     head[2] = image=index($0,"IMAGE") 
     head[3] = command=index($0,"COMMAND") 
     head[4] = created=index($0,"CREATED") 
     head[5] = status=index($0,"STATUS") 
     head[6] = ports=index($0,"PORTS") 
     head[7] = names=index($0,"NAMES") 
    } 
    else{ 
     for (i = 1;i < 8;i++) { 
      if (i!=7){ 
       printf "%s",rtrim(substr($0, head[i], head[i+1] - 1 - head[i])) "|" 
      } 
      else{ 
       printf "%s",rtrim(substr($0, head[i], 100)) "|" 
      } 
     } 
     print "" 
    } 
}') 

arr=($data) 
max_column=7 
row=0 
column=0 

declare -A matrix 

for index in "${!arr[@]}" 
do 
    matrix[$row,$column]=$(echo "${arr[index]}" | tr -d '\n') 
    column=$((column+1)) 
    if [ $((column%max_column)) == 0 ]; then 
     row=$((row+1)) 
     column=0 
    fi 
done 

echo "first container ID is : ${matrix[0,0]}" 
echo "second container ID is : ${matrix[1,0]}" 
echo "third container NAME is : ${matrix[2,6]}" 

を、その目的は、各フィールドの間に|文字を挿入することですデータは、フィールドの内容は、フィールドタイトルと整列するように、我々はheadアレイ内の各フィールド名のインデックスを格納し、次のフィールド位置

に係るトリミング各フィールドを抽出

区切り|連想配列内に注入されます

次に、matrixは最大カラム数(7)に従って構築されます。あなたが正確にフォーマットを知っている限り、各行/列が${matrix[row,column]}

+0

@ bertrand-martelありがとうございました!非常に徹底的な解決策、ここで解決した私の次のステップの束を見て幸せ。興味深いことに、bashで「単純な」概念を実装する方法を学ぶことは興味深いことです。これをPythonやPHPで数分でやったことがありますが、bashのバージョンはかなり長くなっています – aniculescu

+1

おそらく 'IMAGE'異なるフィールド名を持つdocker swarmの 'docker service ls'のような' docker ps'以外のコマンドをサポートしたい場合、一般化することができます。 check [this post](http://stackoverflow.com/questions/42399522/how-to-sort-by-name-docker-service-ls/42401534#42401534) –

+1

確かに、 'ps'コマンドは最も確実でしたこの穏やかな強迫観念の始まり:) – aniculescu

3

、多分試してみてください。

list=$(docker ps) 
IFS=$'\n' array=($list) 

for index in "${!array[@]}" 
do 
    declare -a a=("${array[index]}") 
    printf "%s\n" "${a[@]}" 
done 

適切な引用符を使用しないと、文字列は再分割される可能性があります。あなたのシェルスクリプト@ shell-check.netをチェックすることを検討してください。通常、それはあなたに悪い構文に関するいくつかの良いヒントを与えます。

+0

ありがとう;これは私が期待した通りに機能しました。シェルチェックについて知りませんでしたが、確かにこの学習体験の一部となっています:) – aniculescu

+0

@aniculescu:ようこそ! bashの構文をチェックするサイトは、実際には[shellcheck.net](http://shellcheck.net)です(私は間違いなく何らかの理由でそれをハイフネーションしています)。 –

+0

心配する必要はありません。 vimと崇高に。あまり問題のないサイトを見つけました。 – aniculescu

0

いつもの話で簡単にアクセスすることができます... forループを使用してデータを読み取ることはありませんし、それを制御する方法:

while IFS="\n" read -r line 
do 
    array+=("$line") 
done< <(docker ps) 

個人的に私は、あなたがそれをselectに投げることができるので、線の始めから数値を削除しようとします。そして、それはあなたに関連する項目を参照するのに使用できる数値を与えるでしょう。