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?

Jason Volkoz
la source

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
Tom DeGisi
la source
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
Optimus Prime
la source
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"
Martin Clayton
la source
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 ...

agc
la source
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
欢乐 的 Xiaox
la source
-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
Hendry
la source
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