J'ai un fichier comme ci-dessous:
line1
line2
line3
Et je veux avoir:
prefixline1
prefixline2
prefixline3
Je pourrais écrire un script Ruby, mais c'est mieux si je n'en ai pas besoin.
prefix
contiendra /
. C'est un chemin, /opt/workdir/
par exemple.
# If you want to edit the file in-place
sed -i -e 's/^/prefix/' file
# If you want to create a new file
sed -e 's/^/prefix/' file > file.new
Si prefix
contient /
, vous pouvez utiliser tout autre caractère que celui qui se trouve dans prefix
, ou échapper le /
pour que la commande sed
devienne
's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'
awk '$0="prefix"$0' file > new_file
Avec Perl (remplacement en place):
Perl -pi 's/^/prefix/' file
Vous pouvez utiliser Vim en mode Ex:
ex -sc '%s/^/prefix/|x' file
%
sélectionner toutes les lignes
s
remplace
x
enregistrer et fermer
Si votre préfixe est un peu compliqué, il suffit de le mettre dans une variable:
prefix=path/to/file/
Ensuite, vous transmettez cette variable et laissez awk s'en occuper:
awk -v prefix="$prefix" '{print prefix $0}' input_file.txt
Si vous avez Perl:
Perl -pe 's/^/PREFIX/' input.file
Utiliser le shell:
#!/bin/bash
prefix="something"
file="file"
while read -r line
do
echo "${prefix}$line"
done <$file > newfile
mv newfile $file
Bien que je ne pense pas que Pierr ait cette préoccupation, il me fallait une solution qui ne retarde pas la sortie de la "queue" en direct d'un fichier, car je voulais surveiller plusieurs journaux d'alerte simultanément, en préfixant chaque ligne du nom de son journal. .
Malheureusement, sed, cut, etc. ont introduit trop de mémoire tampon et m'ont empêché de voir les lignes les plus actuelles. La suggestion de Steven Penny d’utiliser l’option -s
de nl
intriguait et les tests ont prouvé qu’elle n’introduisait pas la mise en mémoire tampon indésirable qui me préoccupait.
Il y avait quelques problèmes avec nl
, liés au désir de supprimer les numéros de lignes indésirables (même si vous ne vous souciez pas de leur esthétique, il peut arriver que vous utilisiez des colonnes supplémentaires. serait indésirable). Tout d’abord, utiliser "cut" pour supprimer les chiffres réintroduit le problème de la mise en mémoire tampon, ce qui détruit la solution. Deuxièmement, l'utilisation de "-w1" n'aide pas, car cela ne limite PAS le numéro de ligne à une seule colonne - il s'agrandit à mesure que davantage de chiffres sont nécessaires.
Ce n'est pas joli si vous voulez capturer cela ailleurs, mais puisque c'est exactement ce que je n'avais pas besoin de faire (tout était déjà écrit dans les fichiers journaux, je voulais juste en regarder plusieurs à la fois en temps réel), le meilleur moyen de perdre les numéros de ligne et n’avoir que mon préfixe était de commencer la chaîne -s
avec un retour à la ligne (CR ou ^ M ou Ctrl-M). Donc par exemple:
#!/bin/ksh
# Monitor the widget, framas, and dweezil
# log files until the operator hits <enter>
# to end monitoring.
PGRP=$$
for LOGFILE in widget framas dweezil
do
(
tail -f $LOGFILE 2>&1 |
nl -s"^M${LOGFILE}> "
) &
sleep 1
done
read KILLEM
kill -- -${PGRP}
Voici une solution oneliner très lisible utilisant la commande ts
de moreutils
$ cat file | ts prefix | tr -d ' '
Et comment ça se déroule pas à pas:
# Step 0. create the file
$ cat file
line1
line2
line3
# Step 1. add prefix to the beginning of each line
$ cat file | ts prefix
prefix line1
prefix line2
prefix line3
# Step 2. remove spaces in the middle
$ cat file | ts prefix | tr -d ' '
prefixline1
prefixline2
prefixline3
En utilisant ed:
ed infile <<'EOE'
,s/^/prefix/
wq
EOE
Ceci remplace, pour chaque ligne (,
), le début de la ligne (^
) par prefix
. wq
enregistre et quitte.
Si la chaîne de remplacement contient une barre oblique, nous pouvons utiliser un délimiteur différent pour s
:
ed infile <<'EOE'
,s#^#/opt/workdir/#
wq
EOE
J'ai cité le délimiteur here-doc EOE
("end of ed") pour empêcher l'expansion des paramètres. Dans cet exemple, cela fonctionnerait aussi sans guillemets, mais c'est une bonne pratique d'éviter les surprises si vous avez un $
dans votre script ed.
Il existe un utilitaire unix standard appelé lam
, abréviation de laminate. lam -s prefix file
fera ce que vous voulez. Je l'utilise dans les pipelines, par exemple:
find -type f -exec lam -s "{}: " "{}" \; | fzf
... qui trouvera tous les fichiers, exécutera lam sur chacun d'eux, en donnant à chaque fichier un préfixe de son propre nom de fichier. (Et pompez la sortie vers fzf pour la recherche.)
Voici un exemple résumé utilisant l'approche sed
de cette réponse :
$ cat /path/to/some/file | prefix_lines "WOW: "
WOW: some text
WOW: another line
WOW: more text
function show_help()
{
IT=$(CAT <<EOF
Usage: PREFIX {FILE}
e.g.
cat /path/to/file | prefix_lines "WOW: "
WOW: some text
WOW: another line
WOW: more text
)
echo "$IT"
exit
}
# Require a prefix
if [ -z "$1" ]
then
show_help
fi
# Check if input is from stdin or a file
FILE=$2
if [ -z "$2" ]
then
# If no stdin exists
if [ -t 0 ]; then
show_help
fi
FILE=/dev/stdin
fi
# Now prefix the output
PREFIX=$1
sed -e "s/^/$PREFIX/" $FILE