Qual è il modo più semplice per aggiungere una stringa all'inizio di ogni riga del file dalla riga di comando?


8

Sto cercando un modo per aggiungere una stringa all'inizio di ogni riga (stessa stringa per ogni riga). Non qualcosa di personalizzabile ma piuttosto qualcosa che sarà facile da ricordare e disponibile su ogni piattaforma conforme a POSIX (e anche su ogni shell).

Risposte:


8

Puoi usare sed:

sed -i 's/^/your_string /' your_file

Grazie ai commenti di Stephane e Marco, nota che l' -iopzione non è POSIX. Un modo POSIX per fare quanto sopra sarebbe

sed 's/^/your_string /' your_file > tmp_copy && mv tmp_copy your_file

oppure perl:

perl -pi -e 's/^/your_string /' your_file

Spiegazione

Entrambi i comandi eseguono una sostituzione regex, sostituendo l'inizio di una riga ( ^) con la stringa desiderata. L' -iopzione in entrambi i comandi assicura che il file sia modificato in posizione (ovvero le modifiche si riflettono nel file anziché stampate su stdout).

seddovrebbe essere disponibile su qualsiasi sistema operativo compatibile con POSIX e perldovrebbe essere disponibile sulla maggior parte dei moderni Unices, tranne forse per quelli che hanno attraversato lo sforzo di rimuoverlo.


1
Piccola correzione: l' -iopzione non modifica il file in posizione. Crea un nuovo file e sovrascrive quello originale al termine (prova: l'inode cambia). Non ci sono molti strumenti che eseguono modifiche sul posto, il che è un'operazione pericolosa. Inoltre, poiché menzioni POSIX, lo -iswitch non è obbligatorio per un POSIX compatibile sed, è una caratteristica di alcune implementazioni particolari.
Marco

2
sed -inon è POSIX. È GNU. FreeBSD sedha un'opzione simile, ma è necessario sed -i ''lì.
Stéphane Chazelas,

@Marco Sono consapevole che -icrea una copia temporanea (ecco perché ho detto che le modifiche si riflettono nel file originale); Volevo dire che ottieni la stessa semantica della sostituzione sul posto. Verifica che la risposta aggiornata sia conforme a POSIX.
Joseph R.,

A rigor di termini, le modifiche si riflettono in un nuovo file con lo stesso nome dell'originale.
Keith Thompson,

1
Uso spesso $$(l'ID di processo della shell corrente) come parte di un nome di file temporaneo; evita ogni volta lo sforzo di pensare a un nome univoco garantito:command filename > filename.$$ && mv filename.$$ filename
Keith Thompson,

14
:|paste -d'foo ' - - - - input > output

(sto scherzando, anche se probabilmente troverai la più veloce di tutte le soluzioni pubblicate qui: -b).

Il modo canonico è:

sed 's/^/foo /' < input > output

Tuttavia, non si adatta facilmente alle stringhe arbitrarie. Per esempio,

sed "s/^/$var /"

Funziona solo se $varnon contiene, &, \, /né caratteri di nuova riga.

A tal proposito,

export var
awk '{print ENVIRON["var"], $0}'

o

perl -pe '$_="$ENV{var} $_"'

funzionerebbe meglio.


è qualcosa di interessante ...: P
Rahul Patil,

4

awkPresento una soluzione usando anteporre la stringa "pippo".

awk '{ print "foo", $0; }' input > output

awkè multipiattaforma e disponibile su qualsiasi sistema POSIX. Non esegue modifiche sul posto. Se desideri modificare un file senza crearne un secondo, dovrai utilizzare un file temporaneo. Vedi la sedrisposta di Joseph , mostra la sintassi. Un altro trucco consiste nell'utilizzare la seguente sintassi, che in pratica sta creando un file temporaneo con lo stesso nome del file originale.

{ rm file; awk '{ print "foo", $0 }' > file; } < file

reducto# wc -l foo`914 foo` reducto# { rm foo ; awk '{ print "prepend" , $0 }' > foo } < foo >Questo non sembra funzionare. Ci stavo provando perché il reindirizzamento all'originale mi rendeva nervoso, ma non sarebbe nemmeno iniziato.
Kurtm,

1
Questo esempio funzionerà se utilizza parentesi per l'esterno anziché parentesi graffe.
Kurtm,

4

Puoi evitare i problemi della modifica sul posto con gli strumenti di streaming utilizzando uno strumento che normalmente esegue la modifica sul posto: un editor!

ex sample.txt -c "%s/^/foo /" -c wq

C'è un ulteriore vantaggio che i comandi sono facili e ovvi per chiunque sia esperto nell'unico vero editor.


2

Puoi usare perlper fare questo:

$ perl -pi -e 's/^/mystring /' afile.txt

Esempio

Crea un file di esempio.

$ seq 5 > afile.txt

$ cat afile.txt
1
2
3
4
5

Esegui il comando sopra:

$ perl -pi -e 's/^/mystring /' afile.txt

$ cat afile.txt
mystring 1
mystring 2
mystring 3
mystring 4
mystring 5

Perl sembra essere universale al giorno d'oggi, ma per molto tempo non lo è stato. E sto scommettendo che ci sono un paio di rare varianti UNIX là fuori che rifiutano fermamente di avere il perl come parte della base. Qualcosa di cui essere consapevoli.
Kurtm,

@kurtm vedi la discussione qui . Apparentemente, AIX non ha Perl per impostazione predefinita e nemmeno i sistemi integrati.
terdon

2
@DavidSainty - è abbastanza universale. Il Q è stato taggato con Bash, quindi trovo estremamente difficile immaginare un sistema che abbia Bash ma non Perl. Ad ogni modo, ecco una delle 5 risposte, molte delle altre mostrano come usare sed, ho mostrato come usare il Perl .... non cercare una guerra santa sull'argomento.
slm

1
@DavidSainty Apparentemente solo OpenBSD. Immagino di aver fatto il presupposto poiché gli Open si tendono ad essere conservatori su ciò che consentono in base. OpenBSD lo ha definitivamente nella base.
Kurtm,

1
@slm: " Trovo estremamente difficile immaginare un sistema con Bash ma non Perl ". Ho diversi di questi sistemi seduti sulla mia scrivania. (Capita di essere sistemi embedded.)
Keith Thompson,

1

Semplicemente usando Bash

 while IFS= read -r line; do echo "foo" "${line}" ; done  < input > Output

Usando Python

python -c "import sys; print 'foo '.join([ l for l in sys.stdin.readlines() ])" < input > Output

Se si desidera modificare sul posto

import fileinput
import sys

for line in fileinput.input(['inputfile'], inplace=True):
    sys.stdout.write('foo {l}'.format(l=line))

Link di riferimento


Perché funziona più velocemente di Awk?
Rahul Patil,

1
Funzionerà solo più velocemente che awksu file molto piccoli. Il comportamento varia tra le implementazioni dell'eco e rimuove gli spazi vuoti iniziali e finali e elabora le barre rovesciate in modo speciale.
Stéphane Chazelas,

@StephaneChazelas Sì. hai ragione al 100% appena testato ... paste.ubuntu.com/6210934
Rahul Patil

prefix () { while IFS= read -r REPLY; do printf "%s%s\n" "$1" "$REPLY"; done; }dovrebbe essere più corretto.
Matt,

1
Perché il {}? Penso che @Matt ti stesse suggerendo di trasformarlo in una funzione con nome, a che serve {}senza un nome di funzione?
terdon

-1

Oppure puoi fare quanto segue:

vi filename.txt

Esc(per assicurarti di essere in NORMALmodalità), quindi inserisci il seguente comando:

:1,$ s/^/mystring

Si noti che poiché l'utente richiede ogni riga del file, è possibile sostituire 1,$ semplicemente %. Questo rende il comando :%s/^/string/.
HalosGhost,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.