Est-il possible de le configurer pour toutes les commandes de la fonction / script bash?
Alexander Mills
Réponses:
39
cmd | while read line; do echo "[ERROR] $line"; done
a l'avantage d'utiliser uniquement les commandes intégrées bash, de sorte que moins de processus seront créés / détruits, ce qui devrait être plus rapide que awk ou sed.
@tzrik fait remarquer que cela pourrait aussi faire une belle fonction bash. Définir comme:
function prepend() { while read line; do echo "${1}${line}"; done; }
Cela ne fait en réalité que réduire le nombre de processus par un. (Mais cela pourrait être plus rapide, car aucune expression rationnelle ( sed) ni même stringitting ( awk) n'est utilisé.)
grawity
BTW, j'étais curieux de performance et voici les résultats de mon benchmark simple en utilisant bash, sed et awk. Transférer environ 1000 lignes de texte (sortie dmesg) dans un fichier FIFO, puis les lire comme ceci: pastebin.ca/1606844 On dirait que awk est le gagnant. Des idées pourquoi?
Ilya Zakreuski
1
soyez prudent en exécutant des tests de synchronisation comme ceux-ci - essayez de les exécuter dans les 6 ordres différents, puis de faire la moyenne des résultats. Différents ordres pour atténuer les effets du cache de blocs et moyenne pour atténuer les effets d'interruption / de planification en arrière-plan.
pjz
Cette question est étiquetée "shell", pas "bash".
fiatjaf
1
Assez facile à envelopper dans une fonction aussi:function prepend() { while read line; do echo "${1}${line}"; done; }
Vous pouvez simplement quitter la portée des guillemets pour déréférencer la variable: cmd | awk '{print "['$V]' " $0}'- elle doit être évaluée une fois au début, donc pas de surcharge de performances.
robert
13
Avec tout le mérite de @grawity, je soumets son commentaire comme réponse, car il me semble que cette réponse est la meilleure.
Je suppose que cela dépend de votre but. Si votre objectif est d’ajouter simplement chaque ligne dans un fichier, vous pouvez atteindre cet objectif avec très peu de caractères et un outil très familier. Je préfère de loin cela à un script bash de 10 lignes. Le awkone-liner est assez sympa, mais je pense que plus de gens connaissent sedque awk. Le script bash est bon pour ce qu'il fait, mais il semble qu'il réponde à une question qui n'a pas été posée.
Eric Wilson
La réponse que pjz a soumise est également un bon one-liner. Il n’ajoute pas de programmes ni de processus supplémentaires et peut être exécuté un peu plus rapidement.
user14645
3
sed X cmdlit cmdet ne l'exécute pas. Ou cmd | sed 's/^/[ERROR] /'ou sed 's/^/[ERROR] /' <(cmd)ou cmd > >(sed 's/^/[ERROR] /'). Mais méfiez-vous de ce dernier. Même que cela vous permet d'accéder à la valeur de retour de cmdla sedfonctionne en arrière - plan, il est donc probable que vous voyez la sortie après cmd terminé. Bon pour vous connecter à un fichier, cependant. Et notez que c'est awkprobablement plus rapide que sed.
Tino
Agréable. Cette commande est facilement aliasée. alias lpad="sed 's/^/ /'". au lieu d'ERREUR, j'insère 4 espaces de début. Maintenant, pour le tour de magie: la ls | lpad | pbcopysortie ls sera préfixée de 4 espaces, ce qui le marque en tant que Markdown pour le code , ce qui signifie que vous collez le presse-papiers ( pbcopy le saisit, sur macs) directement dans StackOverflow ou tout autre contexte de démarquage. Impossible de aliasla awk réponse (le 1er essai) si celui - ci gagne. La while read solution est également alias-mesure, mais je trouve cela sed plus expressif.
Dans le cas général, awkc'est le plus rapide. sedest un peu plus lent et perln'est pas beaucoup plus lent que sed. Apparemment, toutes ces langues sont hautement optimisées pour le traitement de texte.
Dans des situations très spéciales, où les forks dominent, exécuter votre script en tant que kshscript compilé ( shcomp) permet de gagner encore plus de temps de traitement. En revanche, il bashest extrêmement lent comparé aux kshscripts compilés .
Créer un binaire statiquement lié à battre awkne semble pas en valoir la peine.
En revanche, pythonc'est très lent, mais je n'ai pas testé de cas compilé, car ce n'est généralement pas ce que vous feriez dans un tel cas de script.
Les variantes suivantes sont testées:
while read line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST] $line"; done
while read -r line; do echo "[TEST]" $line; done
while read -r line; do echo "[TEST]" "$line"; done
sed 's/^/[TEST] /'
awk '{ print "[TEST] " $0 }'
awk -vT="[TEST] " '{ print T $0 }'
awk -vT="[TEST]" '{ print T " " $0 }'
awk -vT="[TEST]" 'BEGIN { T=T " "; } { print T $0 }'
T="[TEST] " awk '{ print ENVIRON["T"] $0 }'
T="[TEST]" awk '{ print ENVIRON["T"] " " $0 }'
T="[TEST]" awk 'BEGIN { T=ENVIRON["T"] " " } { print T $0 }'
perl -ne 'print "[TEST] $_"'
Deux variantes binaires de l'un de mes outils (la vitesse n'est toutefois pas optimisée):
Je voulais une solution qui gère stdout et stderr, alors je l'ai écrite prepend.shet mise sur mon chemin:
#!/bin/bash
prepend_lines(){
local prepended=$1
while read line; do
echo "$prepended" "$line"
done
}
tag=$1
shift
"$@" > >(prepend_lines "$tag") 2> >(prepend_lines "$tag" 1>&2)
Maintenant, je peux juste exécuter prepend.sh "[ERROR]" cmd ..., pour ajouter "[ERREUR]" à la sortie de cmd, et toujours avoir stderr et stdout séparés.
J'ai essayé cette approche mais il y avait quelque chose qui se passait avec ces >(sous-coques que je ne pouvais pas tout à fait résoudre. Il semblait que le script se terminait et que la sortie arrivait au terminal après le retour de l'invite, ce qui était un peu brouillon. J'ai finalement trouvé la réponse ici stackoverflow.com/a/25948606/409638
Réponses:
a l'avantage d'utiliser uniquement les commandes intégrées bash, de sorte que moins de processus seront créés / détruits, ce qui devrait être plus rapide que awk ou sed.
@tzrik fait remarquer que cela pourrait aussi faire une belle fonction bash. Définir comme:
lui permettrait d'être utilisé comme:
la source
sed
) ni même stringitting (awk
) n'est utilisé.)function prepend() { while read line; do echo "${1}${line}"; done; }
Essaye ça:
À votre santé
la source
awk -vT="[ERROR] " '{ print T $0 }'
ouawk -vT="[ERROR]" '{ print T " " $0 }'
T="[ERROR] " awk '{ print ENVIRON["T"] $0 }'
ouT="[ERROR]" awk '{ print ENVIRON["T"] " " $0 }'
cmd | awk '{print "['$V]' " $0}'
- elle doit être évaluée une fois au début, donc pas de surcharge de performances.Avec tout le mérite de @grawity, je soumets son commentaire comme réponse, car il me semble que cette réponse est la meilleure.
la source
awk
one-liner est assez sympa, mais je pense que plus de gens connaissentsed
queawk
. Le script bash est bon pour ce qu'il fait, mais il semble qu'il réponde à une question qui n'a pas été posée.sed X cmd
litcmd
et ne l'exécute pas. Oucmd | sed 's/^/[ERROR] /'
oused 's/^/[ERROR] /' <(cmd)
oucmd > >(sed 's/^/[ERROR] /')
. Mais méfiez-vous de ce dernier. Même que cela vous permet d'accéder à la valeur de retour decmd
lased
fonctionne en arrière - plan, il est donc probable que vous voyez la sortie après cmd terminé. Bon pour vous connecter à un fichier, cependant. Et notez que c'estawk
probablement plus rapide quesed
.alias lpad="sed 's/^/ /'"
. au lieu d'ERREUR, j'insère 4 espaces de début. Maintenant, pour le tour de magie: lals | lpad | pbcopy
sortie ls sera préfixée de 4 espaces, ce qui le marque en tant que Markdown pour le code , ce qui signifie que vous collez le presse-papiers ( pbcopy le saisit, sur macs) directement dans StackOverflow ou tout autre contexte de démarquage. Impossible dealias
la awk réponse (le 1er essai) si celui - ci gagne. La while read solution est également alias-mesure, mais je trouve cela sed plus expressif.J'ai créé un référentiel GitHub pour faire des tests de vitesse.
Le résultat est:
awk
c'est le plus rapide.sed
est un peu plus lent etperl
n'est pas beaucoup plus lent quesed
. Apparemment, toutes ces langues sont hautement optimisées pour le traitement de texte.ksh
script compilé (shcomp
) permet de gagner encore plus de temps de traitement. En revanche, ilbash
est extrêmement lent comparé auxksh
scripts compilés .awk
ne semble pas en valoir la peine.En revanche,
python
c'est très lent, mais je n'ai pas testé de cas compilé, car ce n'est généralement pas ce que vous feriez dans un tel cas de script.Les variantes suivantes sont testées:
Deux variantes binaires de l'un de mes outils (la vitesse n'est toutefois pas optimisée):
Python tamponné:
Et Python sans tampon:
la source
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
pour émettre un horodatagela source
sed 's/^/[ERROR] /'
Je voulais une solution qui gère stdout et stderr, alors je l'ai écrite
prepend.sh
et mise sur mon chemin:Maintenant, je peux juste exécuter
prepend.sh "[ERROR]" cmd ...
, pour ajouter "[ERREUR]" à la sortie decmd
, et toujours avoir stderr et stdout séparés.la source
>(
sous-coques que je ne pouvais pas tout à fait résoudre. Il semblait que le script se terminait et que la sortie arrivait au terminal après le retour de l'invite, ce qui était un peu brouillon. J'ai finalement trouvé la réponse ici stackoverflow.com/a/25948606/409638