如何在Ruby中分割字符串?

时间:2022-09-26 21:37:58

I have special strings like name1="value1" name2='value2'. Values can contain whitespaces and are delimited by either single quotes or double quotes. Names never contain whitespaces. name/value pairs are separated by whitespaces.

我有一些特殊的字符串,比如name1="value1" name2= " value2 "值可以包含空格,可以用单引号或双引号分隔。名称不包含空白。名称/值对由空格分隔。

I want to parse them into a list of name-value pairs like this

我想把它们解析成这样的名称-值对列表

string.magic_split() => { "name1"=>"value1", "name2"=>"value2" }

If Ruby understood lookaround assertions, I could do this by

如果Ruby理解了lookaround断言,我可以这样做

string.split(/[\'\"](?=\s)/).each do |element|
    element =~ /(\w+)=[\'\"](.*)[\'\"]/
    hash[$1] = $2
end

but Ruby does not understand lookaround assertions, so I am somewhat stuck.

但是Ruby不理解lookaround断言,所以我有点困惑。

However, I am sure that there are much more elegant ways to solve this problem anyway, so I turn to you. Do you have a good idea for solving this problem?

然而,我相信有更多更优雅的方法来解决这个问题,所以我转向你。你有解决这个问题的好办法吗?

5 个解决方案

#1


6  

This fails on values like '"hi" she said', but it might be good enough.

她说,这在价值观上失败了,比如“嗨”,但这可能已经足够好了。

str = %q(name1="value1" name2='value 2')
p Hash[ *str.chop.split( /' |" |='|="/ ) ]
#=> {"name1"=>"value1", "name2"=>"value 2"}

#2


2  

This is not a complete answer, but Oniguruma, the standard regexp library in 1.9 supports lookaround assertions. It can be installed as a gem if you are using Ruby 1.8.x.

这不是一个完整的答案,但是Oniguruma, 1.9中的标准regexp库支持查找断言。如果您使用的是Ruby 1.8.x,它可以作为gem安装。

That said, and as Sorpigal has commented, instead of using a regexp I would be inclined to iterate through the string one character at a time keeping track of whether you are in a name portion, when you reach the equals sign, when you are within quotes and when you reach a matched closing quote. On reaching a closing quote you can put the name and value into the hash and proceed to the next entry.

随着Sorpigal注释,而不是使用regexp我会倾向于遍历字符串一个字符时间跟踪是否名称部分,当你到达等号,当你在报价和当你到达一个匹配。在达到一个结束报价时,您可以将名称和值放入散列中,然后继续进入下一个条目。

#3


1  

class String

  def magic_split
    str = self.gsub('"', '\'').gsub('\' ', '\'\, ').split('\, ').map{ |str| str.gsub("'", "").split("=") }
    Hash[str]
  end

end

#4


1  

This should do it for you.

这应该对你有用。

 class SpecialString
   def self.parse(string)
     string.split.map{|s| s.split("=") }.inject({}) {|h, a| h[a[0]] = a[1].gsub(/"|'/, ""); h }
   end
 end

#5


0  

Have a try with : /[='"] ?/

试一下:/[=']?

I don't know Ruby syntax but here is a Perl script you could translate

我不知道Ruby语法,但是这里有一个Perl脚本可以翻译

#!/usr/bin/perl 
use 5.10.1;
use warnings;
use strict;
use Data::Dumper;

my $str =  qq/name1="val ue1" name2='va lue2'/;

my @list = split/[='"] ?/,$str;
my %hash;
for (my $i=0; $i<@list;$i+=3) {
  $hash{$list[$i]} = $list[$i+2];
}
say Dumper \%hash;

Output :

输出:

$VAR1 = {
          'name2' => 'va lue2',
          'name1' => 'val ue1'
        };

#1


6  

This fails on values like '"hi" she said', but it might be good enough.

她说,这在价值观上失败了,比如“嗨”,但这可能已经足够好了。

str = %q(name1="value1" name2='value 2')
p Hash[ *str.chop.split( /' |" |='|="/ ) ]
#=> {"name1"=>"value1", "name2"=>"value 2"}

#2


2  

This is not a complete answer, but Oniguruma, the standard regexp library in 1.9 supports lookaround assertions. It can be installed as a gem if you are using Ruby 1.8.x.

这不是一个完整的答案,但是Oniguruma, 1.9中的标准regexp库支持查找断言。如果您使用的是Ruby 1.8.x,它可以作为gem安装。

That said, and as Sorpigal has commented, instead of using a regexp I would be inclined to iterate through the string one character at a time keeping track of whether you are in a name portion, when you reach the equals sign, when you are within quotes and when you reach a matched closing quote. On reaching a closing quote you can put the name and value into the hash and proceed to the next entry.

随着Sorpigal注释,而不是使用regexp我会倾向于遍历字符串一个字符时间跟踪是否名称部分,当你到达等号,当你在报价和当你到达一个匹配。在达到一个结束报价时,您可以将名称和值放入散列中,然后继续进入下一个条目。

#3


1  

class String

  def magic_split
    str = self.gsub('"', '\'').gsub('\' ', '\'\, ').split('\, ').map{ |str| str.gsub("'", "").split("=") }
    Hash[str]
  end

end

#4


1  

This should do it for you.

这应该对你有用。

 class SpecialString
   def self.parse(string)
     string.split.map{|s| s.split("=") }.inject({}) {|h, a| h[a[0]] = a[1].gsub(/"|'/, ""); h }
   end
 end

#5


0  

Have a try with : /[='"] ?/

试一下:/[=']?

I don't know Ruby syntax but here is a Perl script you could translate

我不知道Ruby语法,但是这里有一个Perl脚本可以翻译

#!/usr/bin/perl 
use 5.10.1;
use warnings;
use strict;
use Data::Dumper;

my $str =  qq/name1="val ue1" name2='va lue2'/;

my @list = split/[='"] ?/,$str;
my %hash;
for (my $i=0; $i<@list;$i+=3) {
  $hash{$list[$i]} = $list[$i+2];
}
say Dumper \%hash;

Output :

输出:

$VAR1 = {
          'name2' => 'va lue2',
          'name1' => 'val ue1'
        };