Commande Shell / Bash pour obtenir la nième ligne de STDOUT

Y a-t-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 faites 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 lors de l'écriture de scripts destinés à être réutilisés, mais lorsque vous travaillez avec le shell au jour le jour, il me serait utile de pouvoir filtrer mon STDOUT de cette manière.

Je me rends également compte que ce serait une commande semi-triviale à écrire (buffer STDOUT, retourner une ligne spécifique), mais je veux savoir s'il y a une commande shell standard pour faire ceci qui serait disponible sans que je laisse tomber un script en place.

159
demandé sur codeforester 2009-09-16 00:53:09

13 réponses

En utilisant sed, juste pour la variété:

ls -l | sed -n 2p

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

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

J'ai vu 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 elle obtient SIGPIPE.

Pour une plage de lignes:

ls -l | sed -n 2,4p

Pour plusieurs plages de lignes:

ls -l | sed -n -e 2,4p -e 20,30p
ls -l | sed -n -e '2,4p;20,30p'
262
répondu Jonathan Leffler 2009-09-15 21:39:20
ls -l | head -2 | tail -1
68
répondu mob 2013-05-07 14:36:20

Alternative à la belle façon tête / queue:

ls -al | awk 'NR==2'

Ou

ls -al | sed -n '2p'
37
répondu ChristopheD 2011-11-16 21:37:51

À Partir 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

À Partir de awk1line:

# print line number 52
awk 'NR==52'
awk 'NR==52 {print;exit}'          # more efficient on large files
20
répondu Mark Edgar 2009-09-24 15:31:54

Par souci d'exhaustivité ;-)

Code Plus Court

find / | awk NR==3

Durée de vie plus courte

find / | awk 'NR==3 {print $0; exit}'
7
répondu Michael Krelin - hacker 2013-05-07 02:24:21

Essayez cette version sed:

ls -l | sed '2 ! d'

Il dit "supprimer toutes les lignes qui ne sont pas la seconde".

6
répondu Dennis Williamson 2009-09-15 21:04:45

Vous pouvez utiliser awk:

ls -l | awk 'NR==2'

Mettre à jour

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

ls -l | awk 'NR==3'
6
répondu Hai Vu 2012-11-09 18:29:16

Perl est-il facilement disponible pour vous?

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

Remplacez évidemment le nombre que vous voulez par 7.

4
répondu catfood 2009-09-15 20:56:39

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 jusqu'à la ligne N soit traité deux fois.

Queue sifflante dans la tête

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

Serait plus efficace?

1
répondu nobody 2014-06-13 23:07:36

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

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
répondu 2009-09-16 14:46:46

Hmm

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

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

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

0
répondu stan 2012-07-20 11:51:29

Pour plus d'exhaustivité..

ls -l | (for ((x=0;x<2;x++)) ; do read ; done ; head -n1)

Jetez les lignes jusqu'à ce que vous arriviez à la seconde, puis imprimez la première ligne après cela. Donc, il imprime la 3ème ligne.

Si c'est juste la deuxième ligne..

ls -l | (read; head -n1)

Mettez autant de lectures que nécessaire.

-1
répondu Shizzmo 2009-09-15 21:50:52

J'ai ajouté cela dans mon .bash_profile

function gdf(){
  DELETE_FILE_PATH=$(git log --diff-filter=D --summary | grep delete | grep $1 | awk '{print $4}')
  SHA=$(git log --all -- $DELETE_FILE_PATH | grep commit | head -n 1 | awk '{print $2}')
  git show $SHA -- $DELETE_FILE_PATH
}

Et ça marche

gdf <file name>
-1
répondu Joel AZEMAR 2016-03-31 10:19:35