Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Suppose I run the following commands:

export STR="abcdef.ghijkl.mnopqr.stuvwy.log"
echo $STR | sed 's/\.[^.]*$//'

I am getting the following result:


Please help me understand the above result.

share|improve this question
In addition to the answers here: echo $STR mangles your string, you're lucky here that it doesn't contain any special characters and so escapes unscathed. Always put double quotes around substitutions: echo "$STR". This can still mangle an initial -; it's best to use printf '%s\n' "$STR", or here use shell string operations and avoid these difficulties. – Gilles Aug 3 '11 at 23:57
up vote 4 down vote accepted

Your sed pattern \.[^.]*$ has only one match to the original string: .log.


  • \. match only a dot character.
  • [^.] matches any character different from .
  • [^.]* matches any sequence of characters different from .
  • $ matches the end of line.

So here the final .log is the only match (.stuvwy.log is not a match because it contains an internal dot). sed will substitute this by the empty string as requested by the command s/\.[^.]*$//. Therefore you end up with:

share|improve this answer
I thought as '.' matches any character except newline, so [^.] would mean matching only newline. If that is not the case, then I agree with your explanation. – nvarun Aug 3 '11 at 19:36
@nvarun: \. matches dot, and . matches anything. As for newlines, they are handled in a special way. The pattern is matched separately against each line, so it's unusual to use \n in sed commands. – Stéphane Gimenez Aug 3 '11 at 19:44
thanks for the clarification. – nvarun Aug 3 '11 at 19:50

If you don't want to use sed you can use the shell's built-in pattern replacement. This is actually faster, not having to call an external program.

${VAR%.*} will remove the match of the glob pattern .* from the end of the string in $VAR. Remember it's a glob and not regex, so a . means a literal ".".

$ foo=aaa.bbbb.2011.log
$ echo ${foo%.*}

See Shell-Parameter-Expansion in the BASH man page for more information.

share|improve this answer

s/\.[^.]*$// == Substitute the first part of the string (because there's no g option at the end to match all occurrences) which starts with a dot (\.), followed by zero or more (*) characters which are not dots ([^.]), placed at the end of the string ($), with the empty string (//).

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.