web-dev-qa-db-fra.com

Commande pour obtenir la nième ligne de STDOUT

Y at-il une commande bash qui vous permettra d’obtenir la nième ligne de STDOUT?

C'est-à-dire quelque chose qui prendrait cette

$ ls -l
-rw-r--r--@ 1 root  wheel my.txt
-rw-r--r--@ 1 root  wheel files.txt
-rw-r--r--@ 1 root  wheel here.txt

et faire quelque chose comme

$ ls -l | magic-command 2
-rw-r--r--@ 1 root  wheel files.txt

Je me rends compte que ce serait une mauvaise pratique d’écrire des scripts destinés à être réutilisés, MAIS lorsqu’on travaille quotidiennement avec Shell, il me serait utile de pouvoir filtrer mon STDOUT de cette manière.

Je réalise aussi que ce serait une commande semi-triviale à écrire (tampon STDOUT, renvoyer une ligne spécifique), mais je veux savoir s’il existe une commande standard Shell pour le faire qui serait disponible sans que je ne lâche un script en place.

190
Alan Storm

En utilisant sed, juste pour varier:

ls -l | sed -n 2p

L'utilisation de cette alternative, qui semble plus efficace puisqu'elle arrête de lire l'entrée lorsque la ligne requise est imprimée, peut générer un SIGPIPE dans le processus d'alimentation, ce qui peut générer un message d'erreur indésirable:

ls -l | sed -n -e '2{p;q}'

J'ai vu cela assez souvent que j'utilise habituellement le premier (ce qui est plus facile à taper de toute façon), bien que ls ne soit pas une commande qui se plaint quand il reçoit SIGPIPE.

Pour une gamme de lignes:

ls -l | sed -n 2,4p

Pour plusieurs gammes de lignes:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'
303
Jonathan Leffler
ls -l | head -2 | tail -1
79
mob

Alternative à la belle tête/queue:

ls -al | awk 'NR==2'

ou

ls -al | sed -n '2p'
39
ChristopheD

De sed1line :

# print line number 52
sed -n '52p'                 # method 1
sed '52!d'                   # method 2
sed '52q;d'                  # method 3, efficient on large files

De awk1line :

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files
21
Mark Edgar

Par souci d'exhaustivité ;-)

code plus court

find / | awk NR==3

durée de vie plus courte

find / | awk 'NR==3 {print $0; exit}'
8

Vous pouvez utiliser awk:

ls -l | awk 'NR==2'

Mise à jour

Le code ci-dessus n'obtiendra pas ce que nous voulons à cause d'une erreur unique: la première ligne de la commande ls -l est le total ligne. Pour cela, le code révisé suivant fonctionnera:

ls -l | awk 'NR==3'
6
Hai Vu

Essayez cette version sed:

ls -l | sed '2 ! d'

Il dit "supprime toutes les lignes qui ne sont pas les secondes".

6
Dennis Williamson

Est-ce que Perl est facilement disponible?

$ Perl -n -e 'if ($. == 7) { print; exit(0); }'

Évidemment, remplacez le nombre que vous voulez par 7.

4
catfood

Une autre affiche suggérée

ls -l | head -2 | tail -1

mais si vous dirigez la tête dans la queue, il semble que tout ce qui va jusqu'à la ligne N soit traité deux fois.

Pipe dans la tête

ls -l | tail -n +2 | head -n1

serait plus efficace?

3
nobody

Oui, le moyen le plus efficace (comme l'a déjà souligné Jonathan Leffler) est d'utiliser sed avec print & stit:

set -o pipefail                        # cf. help set
time -p ls -l | sed -n -e '2{p;q;}'    # only print the second line & quit (on Mac OS X)
echo "$?: ${PIPESTATUS[*]}"            # cf. man bash | less -p 'PIPESTATUS'
0
mco

Hmm

sed n'a pas fonctionné dans mon cas. Je propose:

pour les lignes "impaires" 1,3,5,7 ... ls | awk '0 == (NR + 1)% 2'

pour les lignes "paires" 2,4,6,8 ls | awk '0 == (NR)% 2'

0
stan