How to replace line through sed , but without uncommented?

I am looking to replace minimum password value in login.defs file. it does change , but it change the commented one also.
please

  1. my script to be change 12 in the below line...
sed -i '/PASS_MIN_LEN/c\PASS_MIN_LEN 12' /etc/login.defs

action- It does change, but it change in 2 place.

PASS_MIN_LEN 12  Previous was - #       PASS_MIN_LEN    Minimum acceptable password length.
PASS_MIN_LEN 12

It was replaced #(commented line) also.

Please help the correct sed syntex, which could change the excat value only

Try

sed '/^PASS_MIN_LEN/c\PASS_MIN_LEN 12' /etc/login.defs

This will work only if the setting is left-aligned, which is usually the case, but not necessarily so. Furthermore you are replacing the whole line which would delete comments within the same line, like:

PASS_MIN_LEN     10    # this is a comment

You can make that more robust by:

sed 's/^\([[:space:]]*PASS_MIN_LEN[[:space:]]\)*[0-9][0-9]*/\112/' /etc/login.defs

By the way: you know that PASS_MIN_LEN is obsoleted as it is handled by PAM nowadays, yes?

The second * in the previous post should be

sed 's/^\([[:space:]]*PASS_MIN_LEN[[:space:]]*\)[0-9][0-9]*/\112/' /etc/login.defs

Alternatively one can add a filter condition and use the s command:

sed -i '/^[^#]/ s/PASS_MIN_LEN.*/PASS_MIN_LEN 12/' /etc/login.defs

Or

sed -i '/^#/!s/PASS_MIN_LEN.*/PASS_MIN_LEN 12/' /etc/login.defs

Or branch to the end of the sed script if a comment is met; useful if several commands follow.

sed -i '
  /^#/b
  /PASS_MIN_LEN.*/c\PASS_MIN_LEN 12
' /etc/login.defs