Suppose I run the following commands:

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

I am getting the following result:


I do not understand the above result.

  • 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 'SO- stop being evil' Aug 3 '11 at 23:57

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:

  • 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
  • 1
    @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

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.


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 (//).

Your Answer

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

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