Ajoutez une chaîne de préfixe au début de chaque ligne

334

J'ai un fichier comme ci-dessous:

line1
line2
line3

Et je veux obtenir:

prefixline1
prefixline2
prefixline3

Je pourrais écrire un script Ruby, mais c'est mieux si je n'en ai pas besoin.

prefixcontiendra /. C'est un chemin, /opt/workdir/par exemple.

pierrotlefou
la source

Réponses:

527
# 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 prefixcontient /, vous pouvez utiliser tout autre caractère qui ne se trouve pas dans prefix, ou y échapper /, de sorte que la sedcommande devient

's#^#/opt/workdir#'
# or
's/^/\/opt\/workdir/'
Alok Singhal
la source
1
@benjamin, j'avais déjà voté pour votre réponse, cependant, je préfère sedpour les tâches légères comme celle-ci. Si "préfixe" est connu, il est très facile de choisir un caractère qui ne fait pas partie de "préfixe".
Alok Singhal
1
N'oubliez pas que vous pouvez également utiliser seddans un pipeline, par exemple foo | sed -e 's/^/x /' | bar.
zigg
1
@Dataman cool. Une autre façon serait sed -e '2,$s/^/prefix/'.
Alok Singhal
1
@BinChen échappe à la /même chose \/(dans les chaînes entre guillemets simples) ou \\/(dans les chaînes entre guillemets doubles)
8
À utiliser sed -e 's/$/postfix/' filesi vous souhaitez ajouter une chaîne à la fin de chaque ligne.
Brian
122
awk '$0="prefix"$0' file > new_file

Avec Perl (remplacement en place):

perl -pi 's/^/prefix/' file
Vijay
la source
8
Avec un pipe / stream ou variable:prtinf "$VARIABLE\n" | awk '$0="prefix"$0'
ThorSummoner
2
Avec un fichier volumineux (12 G), des awkrapports awk: out of memory in readrec 1 source line number 1, mais la solution avec se sedtermine avec succès.
jrm
33

Vous pouvez utiliser Vim en mode Ex:

ex -sc '%s/^/prefix/|x' file
  1. % sélectionner toutes les lignes

  2. s remplacer

  3. x sauver et fermer

Steven Penny
la source
1
Pour moi, je viens d'ouvrir le fichier dans vim et type :%s/^/prefix/, car cette stratégie finit par être utile dans de nombreuses situations
Frank Bryce
23

Si votre préfixe est un peu compliqué, mettez-le simplement dans une variable:

prefix=path/to/file/

Ensuite, vous passez cette variable et laissez awk s'en occuper:

awk -v prefix="$prefix" '{print prefix $0}' input_file.txt
Melka
la source
12

Si vous avez Perl:

perl -pe 's/^/PREFIX/' input.file
Majid Azimi
la source
6

Utilisation du shell:

#!/bin/bash
prefix="something"
file="file"
while read -r line
do
 echo "${prefix}$line"
done <$file > newfile
mv newfile $file
ghostdog74
la source
5

Voici une solution tsoneliner très lisible utilisant la commande de moreutils

$ cat file | ts prefix | tr -d ' '

Et comment il est dérivé étape par étape:

# 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
navigaid
la source
'ts' n'est pas installé par défaut sur de nombreuses distributions Linux. En outre, le downvoting parce que le "tr -d ''" de fin dans cette réponse supprimera tous les espaces des lignes, pas seulement l'espace qui a été ajouté par "ts"
Tim Bird
3

Bien que je ne pense pas que pierr ait eu cette préoccupation, j'avais besoin d'une solution qui ne retarderait pas la sortie de la "queue" en direct d'un fichier, car je voulais surveiller plusieurs journaux d'alertes simultanément, en préfixant chaque ligne avec le nom de son journal respectif. .

Malheureusement, sed, cut, etc. ont introduit trop de tampons et m'ont empêché de voir les lignes les plus récentes. La suggestion de Steven Penny d'utiliser l' -soption denl était intrigante, et les tests ont prouvé qu'elle n'introduisait pas la mise en mémoire tampon indésirable qui me concernait.

Il y avait quelques problèmes avec l'utilisation nl liés au désir de supprimer les numéros de ligne indésirables (même si vous ne vous souciez pas de l'esthétique, il peut y avoir des cas où l'utilisation des colonnes supplémentaires ne serait pas souhaitable). Tout d'abord, l'utilisation de «couper» pour supprimer les chiffres réintroduit le problème de mise en mémoire tampon, ce qui détruit la solution. Deuxièmement, l'utilisation de "-w1" n'aide pas, car cela ne restreint PAS le numéro de ligne à une seule colonne - il devient juste plus large car plus de chiffres sont nécessaires.

Ce n'est pas joli si vous voulez capturer cela ailleurs, mais comme c'est exactement ce que je n'avais pas besoin de faire (tout était déjà écrit dans des 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 de n'avoir que mon préfixe était de commencer la -schaîne par un retour chariot (CR ou ^ M ou Ctrl-M). Ainsi, 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}
ScriptGuy
la source
1
utilisez l' -uoption sed pour éviter la mise en mémoire tampon.
Bryan Larsen
2
La mise en mémoire tampon peut être désactivée avec unbuffer / stdbuf, voir unix.stackexchange.com/q/25372/6205
myroslav
2

Utilisation de ed:

ed infile <<'EOE'
,s/^/prefix/
wq
EOE

Ceci remplace, pour chaque ligne ( ,), le début de la ligne ( ^) par prefix. wqenregistre 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 également sans guillemets, mais il est recommandé d'éviter les surprises si vous en avez un $dans votre script ed.

Benjamin W.
la source
2

En utilisant & (toute la partie de l'entrée correspondant au motif »):

cat in.txt | sed -e "s/.*/prefix&/" > out.txt

OU en utilisant des références arrières:

cat in.txt | sed -e "s/\(.*\)/prefix\1/" > out.txt
Ark25
la source
2
  1. Vous pouvez également y parvenir en utilisant la technique de référence arrière

    sed -i.bak 's/\(.*\)/prefix\1/' foo.txt
    
  2. Vous pouvez également utiliser avec awk comme celui-ci

    awk '{print "prefix"$0}' foo.txt > tmp && mv tmp foo.txt
    
k_vishwanath
la source
1

Voici un exemple résumé utilisant l' sedapproche de cette réponse :

$ cat /path/to/some/file | prefix_lines "WOW: "

WOW: some text
WOW: another line
WOW: more text

prefix_lines

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
Brad Parks
la source
2
Cela ne fonctionnera pas si PREFIXcontient des caractères spéciaux pour sed comme une barre oblique.
josch
Bon point ... Si vous trouvez que vous utilisez beaucoup de barres obliques, vous pouvez utiliser un délimiteur différent avec la partie sed, comme détaillé ici , qui vous permettrait de l'utiliser dans les recherches. D'autres caractères spéciaux sed peuvent être ajoutés en s'échappant avec une barre oblique, par exempleprefix_lines \*
Brad Parks
0

Pour les personnes sur les systèmes BSD / OSX, il existe un utilitaire appelé lam, abréviation de stratifié. lam -s prefix filefera 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 sur chacun d'eux, donnant à chaque fichier un préfixe de son propre nom de fichier. (Et pompez la sortie vers fzf pour la recherche.)

Rayon
la source
Vous avez raison, il semble que ce soit une commande BSD uniquement. POSIX l'a remplacé par coller, mais coller n'a pas la fonction d'ajouter une chaîne de séparation complète. Je mettrai à jour ma réponse.
Ray