2017-02-25 6 views
1

목표 : docker ps의 대화 형 버전을 만들려고합니다. 기본적으로,이 각각의 라인은 "메뉴"와 같은 사용자가 할 수있는 일 : 등 시작, 중지, SSH를,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 등)가있을 것 옵션 메뉴를 사용하여 선택한 컨테이너에서 다양한 작업을 수행 할 수 있습니다.

문제점 : 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 블록에서 볼 수 있습니다. declare 문에 관해서는 제 생각에 2 배열을 다루고 있습니다 : 1.배열의 배열 2. 각 줄의 "columns"의 배열 – aniculescu

답변

1

, 당신은 필드 사이를 구분 |를 삽입 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에서 "간단한"개념을 구현하는 법을 배우는 것입니다. 파이썬과 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을 확인해보십시오. 보통 잘못된 구문에 대한 좋은 힌트를 줄 것입니다. 당신이 행/열에서 액세스 할 모든 docker ps 필드 매트릭스 기능을 연관 배열을 갖고 싶어

+0

Thanks; 이것은 예상대로 작동했습니다. 쉘 체크에 대해서는 몰랐지만 확실히이 학습 경험의 일부가되었습니다 :) – aniculescu

+0

@aniculescu : 천만에요! bash 구문을 확인하는 사이트는 실제로 [shellcheck.net] (http://shellcheck.net)입니다. (나는 당신이 그것을 알아 낸 것처럼 보이지만, 실수로 어떤 이유로 든 하이픈을 넣었습니다) –

+0

걱정하지 않아도됩니다. 정력과 승화. 그러나 많은 문제없이 사이트를 알아 냈습니다. – aniculescu

0

일반적인 이야기를 쉽게 액세스 할 수 있습니다 ... for 루프로 데이터를 읽을하지 않고 그것을 제어하는 ​​방법 :

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

개인적으로 나는 라인 1 (1., 2. 등)의 시작 부분에서 숫자를 제거하고 제거 할 수 있습니다. 왜냐하면 선택 항목에 던져 넣을 수 있기 때문에 관련 항목을 참조하는 데 사용할 수있는 숫자를 줄 수 있기 때문입니다.