Suppose I run the following commands:

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

I am getting the following result:

abcdef.ghijkl.mnopqr.stuvwy

Please help me understand the above result.

link|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
feedback

3 Answers

up vote 4 down vote accepted

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

Details:

  • \. 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:

abcdef.ghijkl.mnopqr.stuvwy
link|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
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
thanks for the clarification. – nvarun Aug 3 '11 at 19:50
feedback

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

link|improve this answer
feedback

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%.*}
aaa.bbbb.2011

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

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

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