Drop 1st and last particular character

What is the most efficient way to drop ‘#’ from the first place and last
place if any.

for example:
if input= #hithere# then output = hithere
if input = hithere# then output =hithere
if input = #hithere then output =hithere
if input = hithere then output=hithere

Simplest method is to use Regex.

2012/10/16 ajay paswan [email protected]

output = input.gsub(/^#/, “”)

Oh, I’m an idiot, the end as well:

output = input.gsub(/^#/, “”).gsub(/#$/, “”)

(escape # to prevent interpolation)

or both regexp combined:
#hit#here#”.gsub(/(^#)|(#$)/,’’) #=> “hit#here”

Have you considered python?

my_str = “#hi#there#”
print my_str.strip(’#’)

–output:–
hi#there

python doesn’t make you learn another language to do easy things.

On Tue, Oct 16, 2012 at 9:38 AM, Hans M. [email protected]
wrote:

or both regexp combined:
#hit#here#”.gsub(/(^#)|(#$)/,‘’) #=> “hit#here”

We can also combine by positively matching:

irb(main):001:0> s = “#hit#here#”
=> “#hit#here#”
irb(main):002:0> s = s[/^#?(.*?)#?\z/, 1]
=> “hit#here”

All possible combinations

irb(main):003:0> %w{hi#there #hi#there hi#there# #hi#there#}.each {|s|
p s[/^#?(.*?)#?\z/, 1]}
“hi#there”
“hi#there”
“hi#there”
“hi#there”
=> [“hi#there”, “#hi#there”, “hi#there#”, “#hi#there#”]

Kind regards

robert

You didn’t mention what if you have three times ‘#’.
e.g. input = "#1234#567#
I assume you want output = “1234#567”
Use the String function “sub” which substitute from the first occurrence
only, on the input,
Then reverse the input and use it again (to remove last occurrence)
e.g.:
myString.sub!(’#’,’’)
myString.reverse!.sub!(’#’,’’).reverse!
This will keep all the ‘#’ chars in between.

Sagy

Sagy Drucker wrote in post #1080132:

You didn’t mention what if you have three times ‘#’.
e.g. input = "#1234#567#
I assume you want output = “1234#567”
Use the String function “sub” which substitute from the first occurrence
only, on the input,
Then reverse the input and use it again (to remove last occurrence)
e.g.:
myString.sub!(’#’,’’)
myString.reverse!.sub!(’#’,’’).reverse!
This will keep all the ‘#’ chars in between.

Sagy

No Sagy, that’s not a good method:

“1#1234#567#1”.sub!(’#’,’’).reverse!.sub!(’#’,’’).reverse!
=> “11234#5671”

If you combine it with regex’s “^” and “$” then it would work.

irb(main):010:0> s.gsub /\A#|#\z/, ‘’
=> “aaaa\n#bbb#cc#\n”
irb(main):011:0> s == s.gsub(/\A#|#\z/, ‘’)
=> true

Kind regards

robert

This looks like the best solution.

On Tue, Oct 16, 2012 at 9:38 AM, Hans M. [email protected]
wrote:

or both regexp combined:
#hit#here#”.gsub(/(^#)|(#$)/,‘’) #=> “hit#here”

Few remarks: you do not need the capturing groups. And using \A and
\z is better since it will be really the beginning and the end of the
string. Consider

irb(main):008:0> s = “aaaa\n#bbb#cc#\n”
=> “aaaa\n#bbb#cc#\n”
irb(main):009:0> s.gsub /^#|#$/, ‘’
=> “aaaa\nbbb#cc\n”

Note: the backslash before the second # is needed to avoid string
interpolation confusion.

According to the original specification neither the # before “bbb” has
to be removed nor the one after “cc”. On the contrary with \A and \z
the string remains unchanged which is what should happen:

irb(main):010:0> s.gsub /\A#|#\z/, ‘’
=> “aaaa\n#bbb#cc#\n”
irb(main):011:0> s == s.gsub(/\A#|#\z/, ‘’)
=> true

Kind regards

robert

On Wed, Oct 17, 2012 at 1:58 PM, Joel P. [email protected]
wrote:

irb(main):010:0> s.gsub /\A#|#\z/, ‘’
=> “aaaa\n#bbb#cc#\n”
irb(main):011:0> s == s.gsub(/\A#|#\z/, ‘’)
=> true

This looks like the best solution.

One should use gsub! though if the old String does not need to be
retained - that saves memory because the String is changed in place.

If the old String should be retained this approach might actually be
more efficient since AFAIK both strings share the char buffer if I am
not mistaken:
s = s[/^#?(.*?)#?\z/, 1]

But this is micro optimizing already so better pick what suits you best.

Kind regards

robert

Tangentially, it just occurred to me that ruby’s regular expression
engine does the same thing that javascript’s does, when globally
replacing /X*$/ . It arose when someone wanted to replace any number
(or none) of a character at the start and end of a string with exactly
one of that character.

irb(main):001:0> ‘foo’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo#”
irb(main):002:0> ‘#foo’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo#”
irb(main):003:0> ‘##foo’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo#”
irb(main):004:0> ‘foo#’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”
irb(main):005:0> ‘foo##’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”
irb(main):006:0> ‘##foo##’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”

The original javascript question came up on StackOverflow
http://stackoverflow.com/questions/6147609/how-to-remove-duplicate-character-at-the-end-of-a-string-in-regex

I blogged about it here:


Matthew K., B.Sc (CompSci) (Hons)
http://matthew.kerwin.net.au/
ABN: 59-013-727-651

“You’ll never find a programming language that frees
you from the burden of clarifying your ideas.” - xkcd

Am 17.10.2012 09:39, schrieb Sagy Drucker:

You didn’t mention what if you have three times ‘#’.
e.g. input = "#1234#567#
I assume you want output = “1234#567”
Use the String function “sub” which substitute from the first occurrence only,
on the input,
Then reverse the input and use it again (to remove last occurrence)
e.g.:
myString.sub!(’#’,’’)
myString.reverse!.sub!(’#’,’’).reverse!
This will keep all the ‘#’ chars in between.

this does not work if there is no ‘#’

1.9.3p194 :001 > myString = ‘123’
=> “123”
1.9.3p194 :0ß2 > myString.reverse!.sub!(’#’,’’).reverse!
NoMethodError: undefined method `reverse!’ for nil:NilClass

On Thu, Oct 18, 2012 at 2:51 AM, Matthew K. [email protected]
wrote:

Tangentially, it just occurred to me that ruby’s regular expression
engine does the same thing that javascript’s does, when globally
replacing /X*$/ .

This behavior is common with most regexp engines (at least I don’t
know any which does not behave like this). All regular expressions
X* can match the empty string - anywhere in the input.

irb(main):022:0> “####”.scan /\w*/
=> [“”, “”, “”, “”, “”]

And, when anchoring a portion of the match expression at the end and
have repetition in that match you need to make sure that the
characters are not eaten by other parts of the regexp.

“naive” approach:

irb(main):026:0> %w{aaa aab abb bbb}.each {|s| /.(b)\z/ =~ s; printf
“%p: 1:%p\n”, s, $1}
“aaa”: 1:“”
“aab”: 1:“”
“abb”: 1:“”
“bbb”: 1:“”
=> [“aaa”, “aab”, “abb”, “bbb”]

Working approaches:

  1. reduce greed

irb(main):027:0> %w{aaa aab abb bbb}.each {|s| /.?(b)\z/ =~ s;
printf “%p: 1:%p\n”, s, $1}
“aaa”: 1:“”
“aab”: 1:“b”
“abb”: 1:“bb”
“bbb”: 1:“bbb”
=> [“aaa”, “aab”, “abb”, “bbb”]

  1. negative lookbehind

irb(main):028:0> %w{aaa aab abb bbb}.each {|s| /.(?<!b)(b)\z/ =~ s;
printf “%p: 1:%p\n”, s, $1}
“aaa”: 1:“”
“aab”: 1:“b”
“abb”: 1:“bb”
“bbb”: 1:“bbb”
=> [“aaa”, “aab”, “abb”, “bbb”]

Note though the special case where there is only one alternative with
a match anchored at the end:

irb(main):045:0> for b in body; for pre in segm; for post in segm;
s=“#{pre}#{b}#{post}”; printf “%p → %p\n”,s,s[/#*\z/]; end end end
“” → “”
“#” → “#”
“##” → “##”
“#” → “#”
“##” → “##”
“###” → “###”
“##” → “##”
“###” → “###”
“####” → “####”
“foo” → “”
“foo#” → “#”
“foo##” → “##”
#foo” → “”
#foo#” → “#”
#foo##” → “##”
“##foo” → “”
“##foo#” → “#”
“##foo##” → “##”
=> [“”, “foo”]

Here, the simple expression works since the # are not eaten by other
portions of the regexp.

irb(main):004:0> ‘foo#’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”
irb(main):005:0> ‘foo##’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”
irb(main):006:0> ‘##foo##’.gsub(/\A#|#\Z/, ‘#’)
=> “#foo##”

If one regexp should be used in this case the negative lookbehind is a
viable option since there is no preceding part in this alternative
which we can make non greedy:

irb(main):044:0> for b in body; for pre in segm; for post in segm;
s=“#{pre}#{b}#{post}”; printf “%p → %p\n”,s,s.gsub(/\A#|(?<!#)#\z/,
‘#’); end end end
“” → “#”
“#” → “#”
“##” → “#”
“#” → “#”
“##” → “#”
“###” → “#”
“##” → “#”
“###” → “#”
“####” → “#”
“foo” → “#foo#”
“foo#” → “#foo#”
“foo##” → “#foo#”
#foo” → “#foo#”
#foo#” → “#foo#”
#foo##” → “#foo#”
“##foo” → “#foo#”
“##foo#” → “#foo#”
“##foo##” → “#foo#”
=> [“”, “foo”]

I blogged about it here:
Matthew Kerwin :: Blog :: JS: <code>/x*$/</code> in global replace

Turns out with Oniguruma there is a way to do it with a single
regexp. In fact any regexp engine with lookbehind will do.

Reference: サービス終了のお知らせ

Kind regards

robert