Domanda

Ho un file denominato "insert.txt". Può assomigliare a questo (o brutto):

ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>

E voglio sostituire un blocco di testo in un file di destinazione (target.txt) che è delimitato da "STARTSTACKOVERFLOW" a "STOPSTACKOVERFLOW". (Sto semplificando la questione un po 'qui, ma è lo stesso).

Lo script bash che uso per fare questo è:

TARGETFILE=target.txt
SOURCEFILE=insert.txt
SOURCETXT="$(<$SOURCEFILE)"
DELIMTXT=$(printf "%q" "$SOURCETXT")

sed -i -e "/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/cSTARTSTACKOVERFLOW\n\n${DELIMTXT}\n\nSTOPSTACKOVERFLOW\n" $TARGETFILE

Il problema è che ciò che viene incollato in "target.txt" è in realtà ANSI-C citato:

$'ASDFG?|??|?\/\HJKL<MNBVCXZQWERTYUIOP
zxvbnmlkjhgfdsaqwertyuiop
123"'`~4567890987654321!@#$%^&*()
@#$%^&*()+_}{":?>'

Si noti la $ '', ha aggiunto.

Il motivo è che il printf "% q" sta producendo questo stile citando. Vorrei evitare che -. Però bisogno perché mi deve sfuggire tutta la cattiveria in questo file

C'è un modo migliore di fare quanto sopra utilizzando bash e sed?

È stato utile?

Soluzione

POSIX sed ha un comando 'r' per leggere da un file. Quindi:

sed -i -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/r large.txt' target.txt

L'unico problema è se il file viene letto una volta, o una volta per riga tra le righe di inizio e di arresto. Ho il sospetto che viene letto una volta per linea ... e di lavoro come gettare le linee extra di distanza è più difficile ... ma forse:

sed -i -e '/STOPSTACKOVERFLOW/r large.txt' \
       -e '/STARTSTACKOVERFLOW/,/STOPSTACKOVERFLOW/d' target.txt

semplice demo

Questa versione elimina i marcatori di inizio e fine.

$ cat data
sdasas
adsasdas
start
more
more
end
sdasda
sdasdad
$ cat replace
replace1
replace2
replace3
$ sed -e '/^end$/r replace' -e '/start/,/end/d' data
sdasas
adsasdas
replace1
replace2
replace3
sdasda
sdasdad

Preservare i marcatori di inizio e fine

$ cat sedfile
/^end$/{
a\
start
r replace
a\
end
}
/^start$/,/^end$/d
$ sed -f sedfile data
sdasas
adsasdas
start
replace1
replace2
replace3
end
sdasda
sdasdad
$ 

Questa è fiddlier - non vorrei provare a farlo senza l'utilizzo di un file per lo script, ma si poteva fare così se si voleva. Non è un one-liner, però.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top