Dans Bash, comment ajouter une chaîne après chaque ligne d'un fichier?


112

Comment ajouter une chaîne après chaque ligne dans un fichier en utilisant bash? Cela peut-il être fait en utilisant la commande sed, si oui, comment?

Réponses:


188

Si votre sedpermet l'édition en place via le -iparamètre:

sed -e 's/$/string after each line/' -i filename

Sinon, vous devez créer un fichier temporaire:

typeset TMP_FILE=$( mktemp )

touch "${TMP_FILE}"
cp -p filename "${TMP_FILE}"
sed -e 's/$/string after each line/' "${TMP_FILE}" > filename

Pourquoi avez-vous touchle fichier temporaire? Et je rendrais la sedcommande conditionnelle au succès du cpou l'original pourrait être perdu.
Suspendu jusqu'à nouvel ordre.

J'ai touché le fichier pour réserver rapidement le nom temporaire. Cela peut ne pas être nécessaire. Je pense que vous avez raison de conditionner la commande sed au succès du cp. Pourquoi ne pas modifier le code pour apporter ce correctif. Ça ne me dérange pas un peu!
Bien à

Qu'en est-il d'ajouter une chaîne avant une ligne?
Oxwivi

10
@Oxwivi: sed -e 's/^/string after each line/' -i filename $ signifie fin de ligne. ^ signifie début de ligne.
Tom DeGisi

Si je passe dans sed, sed 's/^/string after each line/'fait ce à quoi je m'attendais (préfixe chaque ligne) mais sed 's/^/string after each line/'ne le fait pas (il remplace la ligne entière par ma chaîne d'ajout). Ce qui donne? Des idées @TomDeGisi?
philadams

17

Je préfère utiliser awk. S'il n'y a qu'une seule colonne, utilisez$0 , sinon remplacez-la par la dernière colonne.

Une manière,

awk '{print $0, "string to append after each line"}' file > new_file

ou ca,

awk '$0=$0"string to append after each line"' file > new_file

1
Aussi, pour ajouter des numéros de ligne (comme c'était dans mon cas), on peut utiliser la NRvariable:awk '{print $0, NR}'
andrybak

2
@optimus J'ai essayé votre méthode, mais en obtenant un espace supplémentaire, une idée sur la façon de les supprimer?
Adil Saju

@AdilSaju sed 's/ //g'cela a fonctionné pour mes besoins, mais cela supprimera de l'espace dans chaque ligne, c'est quelle option gpour et partout dans une ligne.
Eklavyaa

@AdilSaju veuillez ajouter des détails. Mieux vaut poser une nouvelle question.
Optimus Prime

@AdilSaju awk Supprimer , comme {print $0"string to append after each line"}.
Culip le

8

Si vous l'avez, l' utilitaire lam (stratifié) peut le faire, par exemple:

$ lam filename -s "string after each line"

4
  1. Shell POSIX pur et sponge:

    suffix=foobar
    while read l ; do printf '%s\n' "$l" "${suffix}" ; done < file | 
    sponge file
  2. xargset printf:

    suffix=foobar
    xargs -L 1 printf "%s${suffix}\n" < file | sponge file
  3. Utilisation join:

    suffix=foobar
    join file file -e "${suffix}" -o 1.1,2.99999 | sponge file
  4. Outils de Shell en utilisant paste, yes, head & wc:

    suffix=foobar
    paste file <(yes "${suffix}" | head -$(wc -l < file) ) | sponge file

    Notez que pasteinsère un caractère Tab avant $suffix.

Bien sûr, spongepeut être remplacé par un fichier temporaire, ensuite mvpar-dessus le nom de fichier d'origine, comme avec d'autres réponses ...


1
Aucun de ceux-ci n'est préférable sed, à moins que les ressources ne soient très limitées.
agc

J'aime la solution non-sed. sedn'est pas nécessaire pour un travail aussi simple.
Bruce

1

Je préfère echo. en utilisant pure bash:

cat file | while read line; do echo ${line}$string; done

-9

Sed est un peu moche, vous pourriez le faire élégamment comme ceci:

hendry@i7 tmp$ cat foo 
bar
candy
car
hendry@i7 tmp$ for i in `cat foo`; do echo ${i}bar; done
barbar
candybar
carbar

2
Échec pour les fichiers avec plus de lignes que la limite maximale d'arguments du shell. Essayez: chat foo | tout en lisant un; faire echo $ {a} bar; fait ou quelque chose comme ça à la place; c'est un remplacement approprié pour dans la plupart des cas.
alex

1
Il échoue également pour les lignes contenant des espaces.
Suspendu jusqu'à nouvel ordre.

1
Euh, non ça n'échoue pas Dennis. limite maximale d'arguments du shell? Crikey vous êtes pendentif.
hendry

Oui, c'est le cas: $ cat foo foo bar baz alex @ armitage: ~ $ for i in cat foo; faire echo $ {i} bar; fait foobar barbar bazbar mais après quelques tests, je me trompe peut-être sur mon raisonnement, mais Dennis a raison
alex

3
@hendry Oui, cela échoue pour les lignes avec des espaces, par exemple echo "foo bar" | (for i in `cat`; do echo ${i}bar; done)qui imprime 2 lignes même si l'entrée est 1 ligne foo bar(et la catlecture depuis stdin au lieu d'un fichier ne fait aucune différence pour cela).
hyde
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.