1

I'm trying grep 7 lines after match and replace a context in those 7 lines and save it in the same file.

For Example:

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>

i would like to replace the value of MaxRequestsPerChild with 5000.

I have tried with:

grep "IfModule prefork.c" httpd.conf -A7 | /bin/sed -nE "/\bMaxRequestsPerChild\b/ s/[0-9]+/50/"

But no luck.

  • why not just grep for the string you're looking for in the first place? – imabug Jun 21 '18 at 9:25
  • 1
    Sorry if I'm a bit daft, but why not just change the line in an editor? – Kusalananda Jun 21 '18 at 9:25
  • @imabug there are other modules having the same pattern. – user296444 Jun 21 '18 at 9:26
  • 2
    there is several problem here, first, you want to edit a file and you do not provide sed with a file name but with stdin. So sed will never work, I suggest you write a script that get line number with grep and then sed inline at the properline number. I will not help you make this logic a oneliner – Kiwy Jun 21 '18 at 9:28
  • 2
    @nkmoxk You're administrating 73 machines. Are you thinking you would run this over SSH in a loop? Have you considered Ansible? – Kusalananda Jun 21 '18 at 9:30
1

Here is a SED solution.

sed '/<IfModule prefork.c>/,/MaxRequestsPerChild/s/MaxRequestsPerChild.*/MaxRequestsPerChild 5000/' apacheconf

It works by matching the Module name then replacing the next "MaxRequestsPerChild" line with the 5000 value. It will ignore the "MaxRequestsPerChild" of all other modules.

0

With GNU sed (not sure if syntax/feature is okay for other versions)

To change within 6 lines after matching line:

sed -E '/IfModule prefork\.c/{N;N;N;N;N;N;s/(MaxRequestsPerChild +)[0-9]+/\15000/}'

here, N will add a newline to the pattern space, then append the next line of input to the pattern space


If it is always 6th line:

sed -E '/IfModule prefork\.c/{n;n;n;n;n;n;s/[0-9]+/5000/}'

here n will replace the pattern space with the next line of input


Or, simpler syntax with relative addressing

sed -E '/IfModule prefork\.c/,+6 s/(MaxRequestsPerChild +)[0-9]+/\15000/'
  • Thanks, but not getting the result. Looks like problem with [0-9]+ – user296444 Jun 21 '18 at 10:10
  • @nkmoxk can you give details.. did you get an error? or something else happened? it works for me on GNU sed(you've tagged linux, so I'm assuming you have GNU sed) – Sundeep Jun 21 '18 at 10:24
  • its not replacing the value. if i remove + sign, it replaces only the first digit as expected. – user296444 Jun 21 '18 at 10:27
  • did you use sed -E ? may be your version needs sed -r? – Sundeep Jun 21 '18 at 10:46
0

You could put sed's range operator , to good use here in case you are indifferent to line numbers:

sed -e '
   /<IfModule prefork.c>/,\|</IfModule>|!b
   H;\|</IfModule>|!d;g;s/.//;
   s/\(\(\n\)MaxRequestsPerChild[[:blank:]]\{1,\}\)[1-9][0-9]*\n/\15000\2/
' config-file
  1. Store the range in the hold space.
  2. When the range end is detected, retrieve the range from the hold area, and
  3. Perform the desired substitution.
  4. Lines not falling in the range are left to themselves and passed on to stdout.
  • sed -e ' /<IfModule prefork.c>/,\|</IfModule>|!b H;\|</IfModule>|!d;g;s/.//; s/\(\(\n\)MaxRequestsPerChild[[:blank:]]\{1,\}\)[1-9][0-9]*\n/\15000\2/ ' httpd.conf | head -n108 | tail -n1 MaxRequestsPerChild 5000 – user296444 Jun 21 '18 at 12:18
  • Thanks, but its not substituting. – user296444 Jun 21 '18 at 12:19
  • @nkmoxk You cannot write the sed command in one line as you've shown. Give each line of sed code with it's own -e option. – Rakesh Sharma Jun 22 '18 at 5:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy