Comment utiliser la coupe pour séparer par plusieurs espaces blancs?

24

Je voudrais obtenir la dernière colonne de cet exemple:

[  3]  1.0- 2.0 sec  1.00 MBytes  8.39 Mbits/sec
[  3]  2.0- 3.0 sec   768 KBytes  6.29 Mbits/sec
[  3]  3.0- 4.0 sec   512 KBytes  4.19 Mbits/sec
[  3]  4.0- 5.0 sec   256 KBytes  2.10 Mbits/sec
...

Si j'utilise

cut -d\  -f 13

Je reçois

Mbits/sec
6.29
4.19
2.10

car parfois il y a des espaces supplémentaires entre les deux.

rubo77
la source
La dernière colonne est Mbits/sec, c'est ce que vous voulez ou les 2 dernières colonnes?
terdon
1
Je veux seulement obtenir l'avant-dernière colonne, seulement les chiffres
rubo77

Réponses:

17

Pour répondre à votre question littéralement:

sed 's/   */:/g' | cut -d : -f 5

ou

awk -F '  +' '{print $5}'

Mais cela ne fonctionnera pas si le nombre entre parenthèses atteint 10, etc. Si vous êtes uniquement intéressé par les nombres, vous pouvez supprimer tout le reste.

sed 's/[^.0-9][^.0-9]*/:/g' | cut -d : -f 6
Gilles 'SO- arrête d'être méchant'
la source
oui, bien sûr, seuls les chiffres, mais seul votre 3ème exemple fonctionne correctement
rubo77
@ rubo77 Fonctionne pour moi. Les deux premiers exemples font exactement ce que vous demandez dans votre titre. Ou vouliez-vous également retirer l'appareil? Dans ce cas, ajoutez | sed 's/ .*//'à la fin des deux premiers exemples. Bien sûr, il existe de nombreuses autres façons de le faire.
Gilles 'SO- arrête d'être méchant'
un peu plus court avec +au lieu de *: cat test | sed 's / [^. 0-9] \ + /: / g' | cut -d: -f 6
rubo77
@ rubo77 Si votre sed le supporte, c'est. Il est pris en charge par GNU et BusyBox mais pas par exemple par BSD ou Solaris. POSIX spécifie +et ?dans ERE mais laisse \+et \?dans BRE non défini.
Gilles 'SO- arrête d'être méchant'
22

Si nous utilisons la trcommande avec l' option squeeze ( -sindicateur) pour convertir tous les espaces consécutifs multiples en un seul espace, puis effectuer une cutopération avec l'espace comme délimiteur - nous pouvons accéder à la colonne requise portant les nombres.

Reportez-vous au code ci-dessous:

cat file | tr -s ' ' | cut -d ' ' -f 8

Wald Schilfrohr
la source
4
Cette réponse devrait être plus élevée; c'est de loin la solution la plus simple et la plus lisible.
Luke Davis
5

Ces commandes imprimeront toutes la dernière colonne d'un fichier séparé par des espaces:

  • awk '{print $NF}' file

    dans awk, NFest le nombre de champs et $NFest le dernier champ.

  • perl -lane 'print $F[$#F]' file

    -adivise le fichier sur les espaces en tableau @F, $#Fest le nombre d'éléments dans le tableau, tout $F[$#F]comme le dernier élément. Les -nmoyens lisent le fichier donné sur la ligne de commande et appliquent le script transmis -eà chaque ligne. -lajoute simplement un caractère de nouvelle ligne ( \n) à chaque printinstruction.

  • sed 's/.* //g'

    une expression régulière simple qui fait correspondre tout au dernier espace et le supprime, ne laissant que la dernière colonne.

  • rev file | cut -d' ' -f 1 | rev

    revinverse sa sortie pour que le dernier champ soit le premier, cutavec un espace de délimitation pour l'imprimer et revpour ramener le texte à la normale. Cela ne fonctionnera pas si vous avez des espaces consécutifs .

Sur la base de votre contribution, je suppose que vous ne voulez pas réellement la dernière colonne mais l'avant-dernière ou les deux dernières. Dans ce cas, utilisez-les pour imprimer les 2 derniers ( 8.39 Mbits/sec):

awk '{print $(NF-1),$NF}' file 
perl -lane 'print "$F[$#F-1] $F[$#F]"' file 
sed 's/.* \(.* .*\)/\1/' file 
rev file | cut -d' ' -f 1,2 | rev

et ceux-ci pour imprimer l'avant-dernier ( 8.39):

awk '{print $(NF-1)}' file 
perl -lane 'print $F[$#F-1]' file 
sed 's/.* \(.*\) .*/\1/' file 
rev file | cut -d' ' -f 2 | rev
terdon
la source
4

Vous ne pouvez pas séparer plusieurs occurrences d'espaces en utilisant cutle manuel:

Les champs de sortie sont séparés par une seule occurrence du caractère délimiteur de champ.

sauf si le texte est séparé par le même montant ou que vous utilisez trpour en supprimer l'excès.

Sinon, utilisez des outils alternatifs tels que awk, sedou ex.

Par exemple:

ex -s +'%norm $2Bd0' +%p +q! foo.txt

Remplacez +q!par -cwqpour enregistrer les modifications sur place.

kenorb
la source
0

Utilisez un perl one-liner comme ceci:

perl -lane 'print $F[-2]' input_file

Explication:

L'option -eoblige l'interpréteur perl à rechercher le script en ligne, plutôt que dans un fichier.

L'option -nfait que l'entrée (fichier ou STDIN d'un tube) est lue ligne par ligne.

L'option -lsupprime le séparateur d'enregistrement d'entrée (dépendant du système d'exploitation, saut de ligne sur UNIX par défaut) après avoir lu la ligne et l'ajoute à la fin à chaqueprint

L'option -aentraîne la division de chaque ligne d'entrée sur les espaces en tableau @F, et $F[-2]est le deuxième élément comptant à partir de la fin, qui est le champ souhaité. Vous pouvez également utiliser $F[$#F-1], où $#Fest le dernier index du tableau @F, qui est légèrement moins lisible.

Timur Shtatland
la source