문자열에서 부분 문자열 제거


194

다른 문자열에서 문자열을 제거하는 방법이 있는지 궁금합니다. 이 같은:

class String
  def remove(s)
    self[s.length, self.length - s.length]
  end
end

답변:


263

슬라이스 방법을 사용할 수 있습니다.

a = "foobar"
a.slice! "foo"
=> "foo"
a
=> "bar"

'!'가 아닌 버전도. 더 많은 정보는 다른 버전에 대한 문서에서도 볼 수 있습니다 : http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21


1
매우 우아합니다! []뱅이 아닌 버전에 대해 s를 사용할 수도 있습니다 .
Matheus Moreira

65
삭제 된 텍스트 (또는 검색된 텍스트)를 반환하면 부작용이 발생합니다. 삭제 결과 체인 ​​연결이 유감입니다.
Mike

10
얇게 썬 문자열을 어떻게 반환하고 원본에 영향을 미치지 않습니까? 예를 들어 "hello world"가있는 경우 원래 문자열 개체를 수정하지 않고 "hello"를 슬라이스하고 "world"부분 만 반환하려고합니까?
jhabbott

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
어니스트

7
@bcackerman-전달한 delete모든 문자를 삭제하므로 작동하지 않습니다.'hello world'.delete('hello') #=> ' wrd'
rusty

165

에 대해 어떻게 str.gsub("subString", "") 밖으로 확인 루비 문서를


38
subgsubOP는 문자열의 시작 부분에서만 부분 문자열을 제거하기를 원하기 때문에 문자열 보다 더 적합 합니다 (샘플 코드를보십시오). 그리고 이런 식으로 정규 표현식을 사용하는 것이 더 좋습니다 str.sub(/^subString/, '').-하위 문자열이 처음부터 확실하게 제거되도록하기 때문입니다.
Alex D

@AlexD 정규 표현식을 사용하는 것이 더 좋지만 subString정규 표현식 특수 문자를 포함하지 않으면 확실 하지 않습니다.
David Moles

이 경우 @DavidMoles /^subString/는 리터럴이므로 메타 문자를 포함하지 않을 것을 확신 할 수 있습니다. 다른 문자열을 정규식으로 대체하는 경우 다음을 수행 할 수 있습니다 /#{Regexp.escape(str)}/..
Alex D

대답에서 그렇습니다.하지만 OP의 질문에는 없습니다. 에 대한 포인터 주셔서 감사합니다 Regexp.escape().
David Moles

106

문자열의 끝인 경우 다음을 사용할 수도 있습니다 chomp.

"hello".chomp("llo")     #=> "he"

표현식이 a.chomp ( "llo") 인 경우 chomp! 더 정확합니다.
페르난도 곤잘레스 산체스

1
부작용이 없으므로 슬라이스보다 깨끗합니다!
Ardee Aram

5
문자열의 시작 부분 인 경우 다음 chomp과 함께 사용할 수도 있습니다 reverse."hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe

45

대상 문자열이 한 번만 나타나는 경우 다음을 사용할 수 있습니다.

str[target] = ''

또는

str.sub(target, '')

여러 번의 대상 사용이있는 경우 :

str.gsub(target, '')

예를 들어 :

asdf = 'foo bar'
asdf['bar'] = ''
asdf #=> "foo "

asdf = 'foo bar'
asdf.sub('bar', '') #=> "foo "
asdf = asdf + asdf #=> "foo barfoo bar"
asdf.gsub('bar', '') #=> "foo foo "

전체 대체를 수행해야하는 경우 및 의 "!"버전을 사용하십시오 .gsub!sub!


2
루비는 재미있다! asdf['bar'] = ''
Peter Butkovic 님이

1
나는 이것을 "재미"라고 부르지 않을 것입니다. 직관적이지 않을 수도 있습니다.
Jmoney38

31

Rails를 사용하는 경우도 있습니다 remove.

예를 들어 "Testmessage".remove("message")수율 "Test".

경고 :이 방법은 모든 발생을 제거 합니다


1
이것은 바닐라 루비 답변이 아니지만 허용되는 답변은 대부분의 사람들이 찾고있는 것이 아닙니다. 불행하게도 slice슬라이스있어 문자열의 일부를 반환하지 않는 방법, 그것은 "칼"을 반환
딜런 피어스

1
이 수행하는 기능을 구현하기 매우 쉬운 @DylanPierce 그 사용slice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
베넷 Talpers

1
아, 맞습니다. Bang-ifying은 Ruby가 기존 변수를 수정하는 방법입니다. 감사합니다 @ BennettTalpers
Dylan Pierce

27

루비 2.5 이상

만약 당신의 하위 문자열이 문자열의 시작 부분에 있다면, Ruby 2.5는이를위한 방법을 도입했습니다 :

  • delete_prefix문자열의 시작 부분에서 부분 문자열을 제거하기위한
  • 문자열 끝에서 부분 문자열을 제거하기위한 delete_suffix


1

내가 올바르게 해석한다면,이 질문은 문자열 사이의 마이너스 (-) 연산, 즉 내장 플러스 (+) 연산 (연결)의 반대와 같은 것을 요구하는 것 같습니다.

이전 답변과 달리 속성을 준수 해야하는 작업을 정의하려고합니다.

IF c = a + b THEN c-a = b AND c-b = a

이를 위해 세 가지 내장 Ruby 메소드 만 필요합니다.

'abracadabra'.partition('abra').values_at(0,2).join == 'cadabra'.

한 번에 한 가지 방법으로 쉽게 이해할 수 있기 때문에 어떻게 작동하는지 설명하지 않습니다.

개념 증명 코드는 다음과 같습니다.

# minus_string.rb
class String
  def -(str)
    partition(str).values_at(0,2).join
  end
end

# Add the following code and issue 'ruby minus_string.rb' in the console to test
require 'minitest/autorun'

class MinusString_Test < MiniTest::Test

  A,B,C='abra','cadabra','abracadabra'

  def test_C_eq_A_plus_B
    assert C == A + B
  end

  def test_C_minus_A_eq_B
    assert C - A == B
  end

  def test_C_minus_B_eq_A
    assert C - B == A
  end

end

최신 Ruby 버전 (> = 2.0)을 사용하는 경우 마지막 조언 : 이전 예제와 같이 원숭이 패치 문자열 대신 구체화 를 사용 하십시오.

다음과 같이 쉽습니다.

module MinusString
  refine String do
    def -(str)
      partition(str).values_at(0,2).join
    end
  end
end

using MinusString필요한 블록 앞에 추가 하십시오.


개선의 개념에 +1 monkey-patching String 클래스는 아마도이 사용 사례에서 과잉 일 수 있지만, 가끔 원숭이 패치를해야하고 개선의 개념이 실제로 빛을 발해야합니다.
wondersz1

-2

여기 내가 할 일이 있습니다

2.2.1 :015 > class String; def remove!(start_index, end_index) (end_index - start_index + 1).times{ self.slice! start_index }; self end; end;
2.2.1 :016 >   "idliketodeleteHEREallthewaytoHEREplease".remove! 14, 32
 => "idliketodeleteplease" 
2.2.1 :017 > ":)".remove! 1,1
 => ":" 
2.2.1 :018 > "ohnoe!".remove! 2,4
 => "oh!" 

여러 줄로 포맷 :

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end

-7
def replaceslug
  slug = "" + name
    @replacements = [
      [ "," , ""],
      [ "\\?" , ""],
      [ " " , "-"],
      [ "'" , "-"],
      [ "Ç" , "c"],
      [ "Ş" , "s"],
      [ "İ" , "i"],
      [ "I" , "i"],
      [ "Ü" , "u"],
      [ "Ö" , "o"],
      [ "Ğ" , "g"],
      [ "ç" , "c"],
      [ "ş" , "s"],
      [ "ı" , "i"],
      [ "ü" , "u"],
      [ "ö" , "o"],
      [ "ğ" , "g"],
    ]
  @replacements.each do |pair|
    slug.gsub!(pair[0], pair[1])
  end
  self.slug = slug.downcase
end

1
왜 다운 투표가 그렇게 많은가? 당신은 무엇을 잘못했는지 .. 너무 광범위 할 수도있다
zee

OP는 Ö예를 들어 제거 를 요청하지 않았습니다 .
Iulian Onofrei 10
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.