2
votes

sed / Awk / cut ... Comment décider lequel utiliser pour analyser la sortie Docker?

Ma sortie:

docker images | cut -d " " -f1
REPOSITORY
jenkins/jenkins

Je voudrais simplement couper l'identifiant de l'image uniquement à partir de la sortie.

J'ai essayé d'utiliser cut :

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
jenkins/jenkins     lts                 806f56c84444        8 days ago          703MB
mongo               latest              0da05d84b1fe        2 weeks ago         394MB

Le -f1 me donne juste les noms de référentiel, si j'utilise -f3 il a tendance à être vide. Comme le délimiteur n'est pas un espace unique, je ne vois pas comment obtenir la sortie souhaitée.

Pouvons-nous couper en fonction des noms de champs?

I lu la documentation et je n'ai rien vu de pertinent. J'ai également vu qu'il existe un moyen d'y parvenir en utilisant sed / AWK que je suis encore en train de comprendre.

En attendant, y a-t-il un moyen plus simple d'y parvenir en utilisant la commande cut ?

Je suis nouveau sous Unix / Linux, comment puis-je déterminer lequel de Sed / AWK / Cut préférer?


7 commentaires

docker rmi $ (images docker -f "dangling = true" -q)


La commande docker est livrée avec une option --format pour vous permettre d'extraire exactement les champs dont vous avez besoin dans un format adapté à vos besoins. (Certes, l'utilisation de chaînes au format Go n'est pas immédiatement évidente pour nous, non-Go.)


Avec l'astuce du tripleee: docker images --format "{{.ID}}"


Et non, cut ne prend pas en charge l'extraction des champs par nom, bien que ce ne soit pas difficile à faire dans Awk non plus. Voir par exemple stackoverflow.com/questions/45608145/...


Je pense à voter serré: les questions «quelle est la meilleure» sont généralement basées sur une opinion, et ne conviennent pas à ce Q&R.


Ces champs de largeur fixe ou colonnes ou colonnes séparées par des tabulations sont-ils séparés par plusieurs caractères vides ou que contient votre exemple d'entrée publié?


Comme la plupart des outils qui mettent en forme la sortie en colonnes pour l'écran, docker utilise l'équivalent du remplissage d'espace `printf``. Comme mentionné dans ma réponse, les dimensions des colonnes dépendent de la taille de votre écran.Par conséquent, même si les colonnes sont de largeur fixe, les largeurs ne peuvent pas toujours être prédites, ou vous devez utiliser des astuces comme mentir sur les dimensions de votre écran.


6 Réponses :


1
votes

Essayez ceci:

docker images | tr -s ' ' | cut -f3 -d' '

La commande tr -s '' convertit plusieurs espaces en un seul et après coupure, vous pouvez saisir votre champ. Cela fonctionne bien si les valeurs de votre champ n'ont pas d'espaces.


2 commentaires

Nan. Ça ne marche pas. images de docker | cut -f1,2,4 -d $ '\ t' REPOSITORY TAG IMAGE ID CREATED SIZE jenkins / jenkins lts 806f56c84444 il y a 9 jours 703MB mongo dernier 0da05d84b1fe il y a 2 semaines 394MB


images de docker | tr -s '' | cut -f3 -d "" Cela a fonctionné parfaitement



2
votes

Votre entrée semble avoir une largeur fixe de 20 caractères pour chaque champ, vous pouvez donc utiliser la fonction FIELDWIDTHS de gawk.

$ awk -v FIELDWIDTHS="20 20 20 20 20" '{ print $3 }' file
IMAGE ID
806f56c84444
0da05d84b1fe
$
$ awk -v FIELDWIDTHS="20 20 20 20 20" '{ printf "%20s%20s\n", $1, $3 }' file
REPOSITORY          IMAGE ID
jenkins/jenkins     806f56c84444
mongo               0da05d84b1fe

De man gawk :

Si la variable FIELDWIDTHS est définie sur une liste de nombres séparés par des espaces, chaque champ est censé avoir une largeur fixe et gawk divise l'enregistrement en utilisant les largeurs spécifiées. Chaque largeur de champ peut éventuellement être précédée d'une valeur séparée par deux-points spécifiant le nombre de caractères à ignorer avant le début du champ. La valeur de FS est ignorée. L'attribution d'une nouvelle valeur à FS ou FPAT remplace l'utilisation de FIELDWIDTHS.


0 commentaires

2
votes

Vous devez "presser" le remplissage de l'espace dans la sortie par défaut en un seul espace.

1 2 == 1-space-space-2 == Champ 1 avant le 1er espace, Champ entre le 1er et le 2ème espace, Champ 3 après le 2ème espace.

/ p>

couper -d '' -f1 ==> '1'

cut -d '' -f2 ==> '' champ vide entre le 1er et le 2ème délimiteur

couper -d '' -f3 ==> '2'

Donc, dans votre cas, utilisez sed pour remplacer les espaces consécutifs par 1:

images du docker | sed 's / * / / g' | couper -d "" -f1,3

Si la sortie est des largeurs de colonnes fixes, vous pouvez utiliser cette variante de coupe:

images du docker | couper -c1-20,41-60

Cela coupera les colonnes 41 à 60, où nous trouvons l'ID de l'image.

Si jamais la sortie utilise TAB pour le remplissage, vous devez utiliser expand -tn pour que la sortie soit constamment remplie d'espace, puis appliquez le cut -cx approprié, y , par exemple (les nombres peuvent nécessiter un ajustement):

images du docker | développer -t 4 | couper -c1-20,41-60


0 commentaires

0
votes

Avec Modification de texte procédurale c'est:

forEach line {
    if (contains ci "REPOSITORY") { remove }
    keepRange word 2 1
}
removeEmptyLines // <- optional


0 commentaires

1
votes

Dans le cas général, évitez d'analyser les sorties destinées à la consommation humaine. De nombreux utilitaires modernes offrent une option pour produire une sortie dans un format standard comme JSON ou XML, ou même CSV (bien que cela soit moins strictement spécifié et existe dans plusieurs "dialectes").

docker dans particulier a un --format code > option qui vous permet de spécifier votre propre format de sortie:

import docker
client = docker.from_env()
for image in client.images.list():
    print(image.id)

Si vous ne pouvez pas éviter d'écrire votre propre analyseur (en êtes-vous vraiment sûr !? Regardez à nouveau!) , cut convient à la sortie avec un séparateur spécifique à un seul caractère, ou autrement une sortie assez régulière. Pour tout le reste, j'irais avec Awk. Prêt à l'emploi, il analyse les colonnes de séquences d'espaces, donc il fait précisément ce que vous demandez spécifiquement:

sed -n '2,$s/^[^ ]\+[ ]\+[^ ]\+[ ]\+\([^ ]\+\)[ ].*/\1/p'

( NR > 1 saute la première ligne, qui contient les en-têtes de colonne.)

Dans le cas de colonnes de largeur fixe, il vous permet d'extraire une chaîne par index:

XXX

... bien que vous puissiez le faire avec cut aussi:

awk 'NR>1 { sub(/^([^[:space:]]*[[:space:]]+){2}/, ""); sub(/[[:space]].*/, ""); print }'

... mais remarquez que Docker peut ajuster la largeur des colonnes en fonction de la taille de votre écran!

Awk vous permet également d'écrire des extractions d'expressions régulières:

docker images | cut -c41-53

C'est là qu'il chevauche sed:

docker images | awk 'NR>1 { print substr($0, 41, 12) }'

bien que sed soit nettement moins lisible par l'homme, en particulier pour les scripts non triviaux. (C'est encore assez trivial.)

Si vous n'avez jamais utilisé de regex auparavant, ce qui précède semblera énigmatique, mais ce n'est vraiment pas très difficile à séparer. Nous recherchons des séquences de non-espaces (un champ dans une colonne) suivies de séquences d'espaces (un séparateur de colonne) - deux avant le champ ID et tout ce qui vient après, en commençant par le premier espace après la colonne ID. p>

Si vous voulez apprendre les scripts shell, vous devriez probablement aussi apprendre au moins les bases d'Awk (et une familiarité passagère avec sed ). Si vous voulez juste faire le travail et que vous n'êtes peut-être pas spécifiquement intéressé par l'apprentissage des outils U * x (même si vous devriez probablement l'être de toute façon!), Apprenez peut-être plutôt un langage de script moderne comme Python ou Ruby.

... Voici une bibliothèque docker Python :

docker images | awk 'NR>1 { print $3 }'


1 commentaires

Mais vraiment, dites simplement non à passer votre vie à écrire des analyseurs ad hoc pour des formats mal spécifiés avec des cas de coin interminables. J'en suis la preuve vivante: c'est ainsi que réside la folie.



0
votes

Pouvons-nous couper en fonction des noms de champs ? Non.

Comment puis-je déterminer lequel de Sed / AWK / Cut préférer ? YMMV. Pour cette entrée particulière où les champs sont séparés par deux espaces ou plus, en utilisant awk, vous pouvez définir le séparateur de champ sur "+" (deux espaces ou plus), recherchez le nom de champ souhaité ( ID IMAGE ci-dessous) et n'imprimez que ce champ particulier:

$ awk -F"  +" '{if(f=="")for(i=1;i<=NF;i++)if($i=="IMAGE ID")f=i;if(f!="")print $f}' file

Sortie:

IMAGE ID
806f56c84444
0da05d84b1fe

En une seule ligne:

$ awk -F"  +" '                     # set field separator
{
    if(f=="")                       # while we have not determined the desired field
        for(i=1;i<=NF;i++)          # ... keep looking
            if($i=="IMAGE ID")
                f=i
    if(f!="")                       # once found
        print $f                    # start printing it
}' file


0 commentaires