web-dev-qa-db-fra.com

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

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.

299
pierrotlefou
# 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/'
466
Alok Singhal
awk '$0="prefix"$0' file > new_file

Avec Perl (remplacement en place):

Perl -pi 's/^/prefix/' file
115
Vijay

Vous pouvez utiliser Vim en mode Ex:

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

  2. s remplace

  3. x enregistrer et fermer

30
Steven Penny

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
19
Melka

Si vous avez Perl:

Perl -pe 's/^/PREFIX/' input.file
9
Majid Azimi

Utiliser le shell:

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

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}
2
ScriptGuy

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
2
navigaid

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.

1
Benjamin W.

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.)

0
Ray

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

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
0
Brad Parks