Může sed nahradit text řetězcem formátovaným jako tisk ve formátu printf?
Následující příkaz sed nahradí řádek začínající aktuální hodnotou „$domain“ několika hodnotami specifikovanými v proměnných.
/bin/sed "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain} ${limittype} ${limititem} ${value}/" /etc/security/limits.conf
Výstup však nebude správně zarovnán, protože délka hodnot domény atd. není stejná.
Takže výstup by byl něco jako
#oracle hard nproc 131072
oracle hard nproc 666
I když je platný, je obtížně čitelný. Raději bych dostal něco jako
#oracle hard nproc 131072
oracle hard nproc 666
Nejlepší, s čím mohu přijít, abych získal požadovaný výstup, je:
/bin/sed "s/\(^${domain}\)\( *\)\(${limittype}\)\( *\)\(${limititem}\)\( *\)\(.*\)/$EXPL#\1\2\3\4\5\6\7\n${domain}\2${limittype}\4${limititem}\6${value}/" /etc/security/limits.conf
Ale věřím, že musí existovat elegantnější způsob, jak to udělat.
Dokument sed one liners obsahuje některé příklady, které používají zadaný počet znaků, např.
sed -e :a -e 's/^.\{1,78\}$/ &/;ta' # set at 78 plus 1 space
Ale to je v regexp
sekce není v replacement
sekce.
Přijatá odpověď:
Toto používá rozšířenou syntaxi regulárního výrazu -r
, což uklidí spoustu nepořádku. Vzhledem k tomu, že některé hodnoty polí již znáte, nemusíte je ve skutečnosti zpětně odkazovat, což opět snižuje nepořádek (a režii).
&
je speciální náhradní hodnota:drží celý odpovídající vzor. Pomocí &
, opět snižuje nepořádek. Protože se nejedná o zpětnou referenci, má výrazně menší režii.
Použil jsem ( +)
vs. ( *)
. +
předpokládá, že mezi vstupními poli je alespoň jedna mezera. Stačí jej změnit na *
není tomu tak.
EXPL=
dom=oracle
typ=hard
itm=nproc
val=666
echo "oracle hard nproc 131072" |
sed -r "s/^$dom( +)$typ( +)$itm( +).*/$EXPL#&\n$dom\1$typ\2$itm\3$val/"
výstup
#oracle hard nproc 131072
oracle hard nproc 666