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.