2010-09-12 55 views
309

我正在尝试使用字符串的.format方法。但是,如果我把%1%2等字符串中,java.util.UnknownFormatConversionException抛出指向一个令人困惑的Java源代码片:如何在Scala中使用java.String.format?

private void checkText(String s) { 

    int idx; 

    // If there are any '%' in the given string, we got a bad format 
    // specifier. 
    if ((idx = s.indexOf('%')) != -1) { 
     char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1)); 
     throw new UnknownFormatConversionException(String.valueOf(c)); 
    } 
} 

从这个我明白,%字符是被禁止的。如果是这样,那么我应该使用什么参数占位符?

我使用Scala 2.8。

回答

293

虽然以前的所有回复都是正确的,但它们都是Java。这里有一个Scala示例:

val placeholder = "Hello %s, isn't %s cool?" 
val formatted = placeholder.format("Ivan", "Scala") 

我也有一篇关于making format like Python's % operator的博客文章,可能会对您有所帮助。

+56

命名变量“串”烧一些额外的大脑CPU cylces意识到它不是类型,只是一个变量名。只是想指出,这些小东西在解释某些东西时可能会有所作为。 – 2012-09-07 14:32:01

+1

好点,我会解决这个问题。 – pr1001 2012-09-07 19:04:34

+29

为Ivan量身定制的信息+1! – 2013-01-03 21:36:00

297

您不需要使用数字来表示定位。默认情况下,参数的位置只是它在字符串中出现的顺序。

下面是用正确的方法的例子:

String result = String.format("The format method is %s!", "great"); 
// result now equals "The format method is great!". 

你总是会使用%其次是一些其他字符,让方法知道应该如何显示的字符串。 %s可能是最常见的,它只是意味着该参数应该被视为一个字符串。

我就不一一列举每一个选项,但我会举几个例子只是为了给你一个想法:

// we can specify the # of decimals we want to show for a floating point: 
String result = String.format("10/3 = %.2f", 10.0/3.0); 
// result now equals "10/3 = 3.33" 

// we can add commas to long numbers: 
result = String.format("Today we processed %,d transactions.", 1000000); 
// result now equals "Today we processed 1,000,000 transactions." 

String.format只是使用java.util.Formatter,所以你可以在选项的完整描述请参阅Formatter javadocs

而且,如BalusC所述,如果需要,您将在文档中看到可以更改默认参数排序的文档。但是,如果您不止一次地使用相同的参数,那么您可能唯一需要/想要这样做的时间。

126

而不是查看源代码,您应该阅读javadoc String.format()Formatter syntax

您可以在%之后指定值的格式。例如,对于十进制整数是d;而对于字符串是s

String aString = "world"; 
int aInt = 20; 
String.format("Hello, %s on line %d", aString, aInt); 

输出:

Hello, world on line 20 

要做到你尝试过什么(使用参数索引),您可以使用:*n*$

String.format("Line:%2$d. Value:%1$s. Result: Hello %1$s at line %2$d", aString, aInt); 

输出:

Line:20. Value:world. Result: Hello world at line 20 
13

还要注意,Scala的扩展字符串有一些方法(通过隐式转换由PREDEF带来了一个WrappedString),所以你也可以做到以下几点:

val formattedString = "Hello %s, isn't %s cool?".format("Ivan", "Scala") 
8

在斯卡拉2.10

val name = "Ivan" 
val weather = "sunny" 

s"Hello $name, it's $weather today!" 
+1

我认为这仅仅是一个字符串连接的特殊语法(意味着$ name和$ weather是对之前定义的变量的硬引用)。但String.Format将模板作为参数,因此可以从属性文件等中检索模板。 - 上述语法可能吗? – chiccodoro 2013-12-09 09:25:21

+0

它是调用字符串插值,在scala内部有两种类型:s和f,s是简单的字符串,f和printf类似,你甚至可以定义你自己的插值我没有尝试)。 '$ name'表示它需要用变量'name'的值替换,你也可以在插值操作,例如''Hello $ {name.toUpperCase},今天是$ weather !“' – Londo 2014-04-11 16:33:52

70

您可以使用此;

String.format("%1$s %2$s %2$s %3$s", "a", "b", "c"); 

输出:

一个B B C

+1

我从来没有见过这种用法,重复字符串时非常有用,太棒了! – 2013-11-07 05:48:35

+8

+1这更像是你用作C#开发者的东西。在那里,我们使用'{0}'和'{1}'代替'%1 $'和'%2 $'。 – ashes999 2013-11-26 02:36:06

+0

@ ashes999我来自c#land也。我很习惯编号括号,我忘了这不是做事的标准方式。看到百分号将它全部带回来! – 2014-05-12 12:26:17

3

这是一个什么样String.format可以做一个列表。这同样适用于printf

int i = 123; 
o.printf("|%d|%d|%n" ,  i, -i);  // |123|-123| 
o.printf("|%5d|%5d|%n" ,  i, -i);  // | 123| –123| 
o.printf("|%-5d|%-5d|%n" , i, -i);  // |123 |-123 | 
o.printf("|%+-5d|%+-5d|%n" , i, -i);  // |+123 |-123 | 
o.printf("|%05d|%05d|%n%n", i, -i);  // |00123|-0123| 

o.printf("|%X|%x|%n", 0xabc, 0xabc);  // |ABC|abc| 
o.printf("|%04x|%#x|%n%n", 0xabc, 0xabc); // |0abc|0xabc| 

double d = 12345.678; 
o.printf("|%f|%f|%n" ,   d, -d); // |12345,678000|  |-12345,678000| 
o.printf("|%+f|%+f|%n" ,  d, -d); // |+12345,678000| |-12345,678000| 
o.printf("|% f|% f|%n" ,  d, -d); // | 12345,678000| |-12345,678000| 
o.printf("|%.2f|%.2f|%n" ,  d, -d); // |12345,68| |-12345,68| 
o.printf("|%,.2f|%,.2f|%n" , d, -d); // |12.345,68| |-12.345,68| 
o.printf("|%.2f|%(.2f|%n",  d, -d); // |12345,68| |(12345,68)| 
o.printf("|%10.2f|%10.2f|%n" , d, -d); // | 12345,68| | –12345,68| 
o.printf("|%010.2f|%010.2f|%n",d, -d); // |0,68| |-,68| 

String s = "Monsterbacke"; 
o.printf("%n|%s|%n", s);     // |Monsterbacke| 
o.printf("|%S|%n", s);     // |MONSTERBACKE| 
o.printf("|%20s|%n", s);     // |  Monsterbacke| 
o.printf("|%-20s|%n", s);     // |Monsterbacke  | 
o.printf("|%7s|%n", s);     // |Monsterbacke| 
o.printf("|%.7s|%n", s);     // |Monster| 
o.printf("|%20.7s|%n", s);    // |    Monster| 

Date t = new Date(); 
o.printf("%tT%n", t);      // 11:01:39 
o.printf("%tD%n", t);      // 04/18/08 
o.printf("%1$te. %1$tb%n", t);   // 18. Apr 
1

虽然@Londo提到Scala的“S”串插,我认为Scala的"f" string interpolator是更相关的原题。本例中使用其他反应过一段时间也可以写成(因为斯卡拉2.10)这样说:

scala> val name = "Ivan" 
name: String = Ivan 
scala> val thing = "Scala" 
thing: String = Scala 
scala> val formatted = f"Hello $name%s, isn't $thing%s cool?" 
formatted: String = Hello Ivan, isn't Scala cool? 

原来的问题的连接是必须认识到:

  • formatted与定义一个以字母“f”为前缀的字符串。这是“f”(格式化)字符串内插器。
  • 的“F”串插使用java.util.Formatter
  • java.lang.String.format使用约串插在同一java.util.Formatter

的好处是,它可以让你看到哪些变量直接代入字符串,而不必的将其与String.format方法的参数相匹配。

0

在Scala中,字符串插值我们$,节省了一天,让我们的生活更轻松:

例如:你要定义一个函数,输入姓名和年龄,并说你好用这个名字说出它的年龄。 可以这样写:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is $age" 

因此,当你调用这个函数:是这样的:

funcStringInterpolationDemo("Shivansh",22) 

它的输出将是:

Hey ! my name is Shivansh and my age is 22 

您可以编写代码在同一行中改变它,就好像你想把年龄增加10岁!

然后函数可以是:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is ${age+10}" 

而且现在的输出将是:

Hey ! my name is Shivansh and my age is 32