Can sed replace text with a string formatted like printf's formatted printing?
The following sed command replaces a line starting with the current value of "$domain" with several values specified in variables.
/bin/sed "s/\(^${domain} *${limittype} * ${limititem}.*\)/$EXPL#\1\n${domain} ${limittype} ${limititem} ${value}/" /etc/security/limits.conf
However the output will not be properly aligned because the length of the values of domain etc. are not the same.
So the output would be something like
#oracle hard nproc 131072
oracle hard nproc 666
While valid, it is difficult to read. I would prefer to get something like
#oracle hard nproc 131072
oracle hard nproc 666
The best I can come with to get the desired output is:
/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
But I believe there must a more elegant way to do this.
The sed one liners document contains some examples that use a specified number of characters, e.g.
sed -e :a -e 's/^.\{1,78\}$/ &/;ta' # set at 78 plus 1 space
But this is in the regexp
section not in the replacement
section.
Best Answer
This uses the extended regex syntax
-r
, which clears up a lot of the clutter. Also, because you already know some of the field values, you don't actually need to back-reference them, again reducing clutter (and overhead).&
is a special replacement value: it hold the entire matched pattern. Using the&
, again reduces clutter. As it is not a back-reference, it has significantly less overhead.I've used
( +)
vs.( *)
. The+
assumes that there is at least one space between input fields. Just change it to the*
it that is not the case.output