En supposant un simple grep tel que:
$ psa aux | grep someApp
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Cela fournit beaucoup d'informations, mais comme la première ligne de la commande ps est manquante, il n'y a pas de contexte pour l'information. Je préférerais que la première ligne de ps soit également affichée:
$ psa aux | someMagic someApp
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Bien sûr, je pourrais ajouter un regex à grep spécifiquement pour ps:
$ ps aux | grep -E "COMMAND|someApp"
Cependant, je préférerais une solution plus générale car il existe d'autres cas dans lesquels j'aimerais également avoir la première ligne.
Cela semble être un bon cas d’utilisation pour un descripteur de fichier "stdmeta" .
bash
command-line
dotancohen
la source
la source
ack
sont si utiles, et pourquoiperl
passé sont montés en flèchesed
,awk
etc. en popularité: il est important pour les parties à résumer en un tout cohérent.-C
argument deps
et vous n'avez pas besoin de le canaliser dans grep. par exempleps u -C someApp
ou mêmeps u -C app1 -C app2 -C app3
ps aux | { head -1; grep foo; }
mentionnée par @Nahuel Fouilleul ci-dessous (c'est probablement la seule solution que je pourrais rappeler sur place si nécessaire)Réponses:
Bonne façon
Normalement, vous ne pouvez pas faire cela avec grep, mais vous pouvez utiliser d'autres outils. AWK a déjà été mentionné, mais vous pouvez également utiliser
sed
, comme ceci:Comment ça fonctionne:
L'utilitaire Sed fonctionne sur chaque ligne individuellement, en exécutant des commandes spécifiées sur chacune d'entre elles. Vous pouvez avoir plusieurs commandes, en spécifiant plusieurs
-e
options. Nous pouvons ajouter à chaque commande un paramètre de plage spécifiant si cette commande doit être appliquée à une ligne spécifique ou non."1p" est une première commande. Il utilise une
p
commande qui affiche normalement toutes les lignes. Mais nous le préfixons avec une valeur numérique qui spécifie la plage à laquelle il doit être appliqué. Ici, nous utilisons1
ce qui signifie première ligne. Si vous souhaitez imprimer plus de lignes, vous pouvez utiliserx,yp
oùx
est la première ligne pour imprimer,y
est la dernière ligne pour imprimer. Par exemple, pour imprimer les 3 premières lignes, vous utiliseriez1,3p
La commande suivante est celle
d
qui supprime normalement toutes les lignes du tampon. Avant cette commande, nous mettonsyourpattern
entre deux/
caractères. C’est l’autre façon (en premier lieu de spécifier les lignes que nous avons utilisées avec lap
commande) d’adressage des lignes sur lesquelles la commande devrait être exécutée. Cela signifie que la commande ne fonctionnera que pour les lignes qui correspondentyourpattern
. Sauf que nous utilisons!
caractère avantd
commande qui inverse sa logique. Alors maintenant, toutes les lignes qui ne correspondent pas au motif spécifié seront supprimées .À la fin, sed imprimera toutes les lignes laissées en mémoire tampon. Mais nous avons supprimé les lignes qui ne correspondent pas du tampon afin que seules les lignes correspondantes soient imprimées.
Pour résumer: nous imprimons la 1ère ligne, puis nous supprimons toutes les lignes qui ne correspondent pas à notre modèle d'entrée. Reste des lignes sont imprimées (donc seulement des lignes qui font correspondre au modèle).
Problème de première ligne
Comme mentionné dans les commentaires, cette approche pose problème. Si le motif spécifié correspond également à la première ligne, il sera imprimé deux fois (une fois par
p
commande et une fois en raison d'une correspondance). Nous pouvons éviter cela de deux manières:Ajout de
1d
commande après1p
. Comme je l'ai déjà mentionné, lad
commande supprime les lignes du tampon et nous spécifions sa plage par le numéro 1, ce qui signifie qu'elle supprimera uniquement la 1ère ligne. Donc, la commande seraitsed -e '1p' -e '1d' -e '/youpattern/!d'
Utiliser la
1b
commande au lieu de1p
. C'est un tourb
Cette commande nous permet de passer à une autre commande spécifiée par une étiquette (certaines commandes peuvent ainsi être omises). Mais si cette étiquette n'est pas spécifiée (comme dans notre exemple), il saute simplement à la fin des commandes, ignorant le reste des commandes pour notre ligne. Donc, dans notre cas, la dernièred
commande ne supprimera pas cette ligne du tampon.Exemple complet:
Utiliser le point-virgule
Certaines
sed
implémentations peuvent vous épargner une certaine frappe en utilisant un point-virgule pour séparer des commandes au lieu d'utiliser plusieurs-e
options. Donc, si vous ne vous souciez pas d'être portable, la commande le seraitps aux | sed '1b;/syslog/!d'
. Cela fonctionne au moins dansGNU sed
et lesbusybox
implémentations.Façon folle
Voici cependant une façon assez folle de faire cela avec grep. Ce n'est certainement pas optimal, je le publie uniquement à des fins d'apprentissage, mais vous pouvez l'utiliser par exemple, si vous n'avez aucun autre outil dans votre système:
Comment ça fonctionne
Tout d'abord, nous utilisons l'
-n
option pour ajouter des numéros de ligne avant chaque ligne. Nous voulons numéroter toutes les lignes auxquelles nous correspondons.*
- n'importe quoi, même les lignes vides. Comme suggéré dans les commentaires, nous pouvons également faire correspondre '^', le résultat est le même.Ensuite, nous utilisons des expressions régulières étendues pour pouvoir utiliser
\|
un caractère spécial qui fonctionne comme OR. Nous faisons donc correspondre si la ligne commence par1:
(première ligne) ou contient notre modèle (dans ce cas, sonsyslog
).Problème de numéros de ligne
Maintenant, le problème est que nous obtenons ces numéros de ligne laids dans notre sortie. Si cela pose un problème, nous pouvons les supprimer avec
cut
, comme ceci:-d
option spécifie le délimiteur,-f
spécifie les champs (ou colonnes) que nous voulons imprimer. Nous voulons donc couper chaque ligne sur chaque:
caractère et imprimer uniquement la deuxième colonne et toutes les colonnes suivantes. Cela supprime efficacement la première colonne avec son délimiteur et c'est exactement ce dont nous avons besoin.la source
cat -n
et sera plus claire qu'avec un grep abusé pour cela.nl
ne compte pas les lignes vides (mais les affiche sans numéro de ligne),cat -n
formate la numérotation avec les espaces précédents,grep -n .
supprime les lignes vides et ajoute deux points. Tous ont leurs ...ps aux | sed '1p;/pattern/!d'
imprimera la première ligne deux fois si elle correspond au motif . Le mieux est de utilisé lab
commande:ps aux | sed -e 1b -e '/pattern/!d'
.cat -n
n'est pas POSIX.grep -n '^'
numéroter chaque ligne (pas un problème pour la sortie ps qui n'a pas de lignes vides).nl -ba -d $'\n'
numérote chaque ligne.1b;...
n'est pas portable ni POSIX, il ne peut y avoir aucune autre commande après "b", vous avez donc besoin d'une nouvelle ligne ou d'une autre expression -e.Que pensez-vous d'utiliser
awk
au lieu degrep
?NR == 1
: Numéro d'enregistrement == 1; c'est à dire. la première ligne||
: ou:/syslogd/
: Modèle à rechercherCela pourrait également valoir la peine d’être examiné
pgrep
, même s’il s’agit davantage de scripts que de sorties orientées vers les utilisateurs. Cela évite toutefois que lagrep
commande elle-même apparaisse dans la sortie.la source
EDIT: après les commentaires
Bien que
head -1
je lise toutes les entrées, mais après les avoir testées, cela fonctionne aussi.la sortie est
la source
{ IFS='' read line; ... }
au cas où l'en-tête commence par des espaces.head -1
place du combo lecture / écho.head -n1
ma bash. Cela peut probablement être spécifique à la mise en œuvre. Ma tête ne lit pas toute l'entrée dans ce cas, seulement la première ligne, laissant le reste d'entre eux dans le tampon d'entrée.head -n1
est plus court, mais il semble que même la spécification POSIX ne précise pas quelle quantité de son entrée est autorisée à lire, elle est donc peutread line; echo $line
- être plus portable après tout.Filtre interne de support ps,
Supposons que vous recherchiez un processus bash:
ps -C bash -f
Dresse la liste de tous les processus nommés
bash
.la source
J'ai tendance à envoyer l'en-tête à stderr :
Ceci est généralement suffisant pour la lecture humaine. par exemple:
La partie entre crochets pourrait entrer dans son propre script pour une utilisation générale.
Il y a une commodité supplémentaire en ce sens que la sortie peut être acheminée plus loin (vers
sort
etc.) et que l'en-tête restera au-dessus.la source
Vous pouvez également utiliser
tee
ethead
:Notez cependant que tant qu’il
tee
est impossible d’ignorer lesSIGPIPE
signaux (voir par exemple la discussion ici ), cette solution nécessite une solution de contournement pour être fiable. La solution de contournement consiste à ignorer les signaux SIGPIPE, ceci peut par exemple être fait comme ceci dans bash comme des obus:Notez également que l' ordre de sortie n'est pas garanti .
la source
grep
:| { sleep .5; cat }
.Peut-être que deux
ps
commandes seraient les plus faciles.la source
ps aux
appel et le deuxième appel ... Et si vous voulez juste cette première ligne statique, pourquoi ne pas y revenir manuellement?Vous pouvez utiliser pidstat avec:
Exemple:
Informations complémentaires: http://linux.die.net/man/1/pidstat
la source
Placez ce qui suit dans votre fichier .bashrc ou copiez / collez d’abord dans un shell pour le tester.
Utilisation: psls [modèle grep]
Assurez-vous de source votre .bashrc (ou .bash_profile si vous le mettez là à la place):
La fonction se complétera même automatiquement sur la ligne de commande du shell. Comme vous l'avez dit dans une autre réponse, vous pouvez diriger la première ligne vers un fichier pour enregistrer un appel sur ps.
la source
psl
, qui n'appelle queps
etgrep
une fois chacune (et dont on n'a pas besoinhead
).trier mais garder la ligne d'en-tête en haut
Et l'utiliser comme ça
la source
Merci surtout à Janis Papanagnou dans comp.unix.shell, j'utilise la fonction suivante:
Cela présente de nombreux avantages:
-i
pour la correspondance sans-E
distinction de casse, pour les expressions rationnelles étendues, etc.Exemple d'utilisation:
la source
Une autre façon avec
gnu ed
:ou, si le shell prend en charge la substitution de processus:
C'est:
Plus portable, sans
gnu
'!'
substitution de shell, utilisez uniquemented
intégrér
pourr
insérer la sortie deps aux
dans la mémoire tampon, puis supprimez les lignes non correspondantes dans la2,$
plage et imprimez le résultat:Et puisque les
sed
commandes de la sortie de réponse acceptée aussi la ligne se correspondant, avec unsed
qui prend en charge-f-
et une coque qui prend en charge la substitution de processus que je courrais:qui fait à peu près la même chose que les
ed
commandes précédentes .la source
La manière Perl:
Bien plus facile à lire que
sed
, plus rapidement, aucun risque de tracer des lignes indésirables.la source
Si cela ne concerne que les processus grepping avec des en-têtes complets, j'aimerais développer la suggestion de @ mrb:
pgrep bash | xargs ps -fp
vous obtiendrez le même résultat mais sans sous-shell. Si un autre formatage est requis:la source
Si vous connaissez les numéros de ligne exacts, c'est facile avec perl! Si vous voulez obtenir les lignes 1 et 5 d'un fichier, dites / etc / passwd:
Si vous souhaitez également obtenir d'autres lignes, ajoutez simplement leurs numéros dans le tableau.
la source