Vous cherchez quelque chose comme ça? Des idées?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Vous cherchez quelque chose comme ça? Des idées?
cmd | prepend "[ERRORS] "
[ERROR] line1 text
[ERROR] line2 text
[ERROR] line3 text
... etc
Réponses:
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; }
lui permettrait d'être utilisé comme:
cmd | prepend "[ERROR] "
sed
) ni même stringitting ( awk
) n'est utilisé.)
function prepend() { while read line; do echo "${1}${line}"; done; }
Essaye ça:
cmd | awk '{print "[ERROR] " $0}'
À votre santé
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.
sed 's/^/[ERROR] /' cmd
awk
one-liner est assez sympa, mais je pense que plus de gens connaissent sed
que 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.
sed X cmd
lit cmd
et 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 cmd
la sed
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'est awk
probablement plus rapide que sed
.
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 | 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 de alias
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 et perl
n'est pas beaucoup plus lent que sed
. 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, il bash
est extrêmement lent comparé aux ksh
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:
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):
./unbuffered.dynamic -cp'[TEST] ' -q ''
./unbuffered.static -cp'[TEST] ' -q ''
Python tamponné:
python -uSc 'import sys
for line in sys.stdin: print "[TEST]",line,'
Et Python sans tampon:
python -uSc 'import sys
while 1:
line = sys.stdin.readline()
if not line: break
print "[TEST]",line,'
awk -v T="[TEST %Y%m%d-%H%M%S] " '{ print strftime(T) $0 }'
pour émettre un horodatage
Je voulais une solution qui gère stdout et stderr, alors je l'ai écrite prepend.sh
et 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.
>(
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