[java] 문자열 형식의 명명 된 자리 표시 자

파이썬에서 문자열을 포맷 할 때 자리 표시자를 위치가 아닌 이름으로 채울 수 있습니다.

print "There's an incorrect value '%(value)s' in column # %(column)d" % \
  { 'value': x, 'column': y }

Java에서 가능할지 궁금합니다 (외부 라이브러리없이).



답변

자카르타 커먼즈 랭의 StrSubstitutor는 값이 이미 올바르게 형식화 된 경우이를 수행하는 간단한 방법입니다.

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/text/StrSubstitutor.html

Map<String, String> values = new HashMap<String, String>();
values.put("value", x);
values.put("column", y);
StrSubstitutor sub = new StrSubstitutor(values, "%(", ")");
String result = sub.replace("There's an incorrect value '%(value)' in column # %(column)");

위의 결과는 다음과 같습니다.

“2 번 열에 잘못된 값 ‘1’이 있습니다.”

Maven을 사용할 때이 종속성을 pom.xml에 추가 할 수 있습니다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>


답변

확실 하지 않지만 MessageFormat 을 사용 하여 하나의 값을 여러 번 참조 할 수 있습니다 .

MessageFormat.format("There's an incorrect value \"{0}\" in column # {1}", x, y);

위의 내용은 String.format ()으로도 수행 할 수 있지만 복잡한 표현식을 작성 해야하는 경우 messageFormat 구문 클리너를 찾고 문자열에 넣는 객체의 유형에 신경 쓰지 않아도됩니다.


답변

단순한 이름 지정된 자리 표시자를위한 Apache Common StringSubstitutor 의 또 다른 예입니다 .

String template = "Welcome to {theWorld}. My name is {myName}.";

Map<String, String> values = new HashMap<>();
values.put("theWorld", "Stackoverflow");
values.put("myName", "Thanos");

String message = StringSubstitutor.replace(template, values, "{", "}");

System.out.println(message);

// Welcome to Stackoverflow. My name is Thanos.


답변

StringTemplate 라이브러리 를 사용할 수 있으며 원하는 것을 제공합니다.

import org.antlr.stringtemplate.*;

final StringTemplate hello = new StringTemplate("Hello, $name$");
hello.setAttribute("name", "World");
System.out.println(hello.toString());


답변

내용은 매우 간단한 경우 당신은 단순히 하드 코드 된 문자열 교체가 도서관에 대한 필요를 사용할 수 없습니다 :

    String url = "There's an incorrect value '%(value)' in column # %(column)";
    url = url.replace("%(value)", x); // 1
    url = url.replace("%(column)", y); // 2

경고 : 방금 가장 간단한 코드를 보여주고 싶었습니다. 물론 주석에 명시된 바와 같이 보안이 중요한 심각한 생산 코드에는 사용하지 마십시오. 이스케이프, 오류 처리 및 보안이 여기에 있습니다. 그러나 최악의 경우 이제 ‘좋은’lib를 사용해야하는 이유를 알 수 있습니다 🙂


답변

모든 도움을 주셔서 감사합니다! 모든 단서를 사용하여 원하는 것을 정확하게 수행하는 루틴을 작성했습니다. 사전을 사용하여 파이썬과 같은 문자열 형식. 내가 Java 초보자이기 때문에 모든 힌트를 주시면 감사하겠습니다.

public static String dictFormat(String format, Hashtable<String, Object> values) {
    StringBuilder convFormat = new StringBuilder(format);
    Enumeration<String> keys = values.keys();
    ArrayList valueList = new ArrayList();
    int currentPos = 1;
    while (keys.hasMoreElements()) {
        String key = keys.nextElement(),
        formatKey = "%(" + key + ")",
        formatPos = "%" + Integer.toString(currentPos) + "$";
        int index = -1;
        while ((index = convFormat.indexOf(formatKey, index)) != -1) {
            convFormat.replace(index, index + formatKey.length(), formatPos);
            index += formatPos.length();
        }
        valueList.add(values.get(key));
        ++currentPos;
    }
    return String.format(convFormat.toString(), valueList.toArray());
}


답변

이것은 오래된 스레드이지만 레코드 용으로 다음과 같이 Java 8 스타일을 사용할 수도 있습니다.

public static String replaceParams(Map<String, String> hashMap, String template) {
    return hashMap.entrySet().stream().reduce(template, (s, e) -> s.replace("%(" + e.getKey() + ")", e.getValue()),
            (s, s2) -> s);
}

용법:

public static void main(String[] args) {
    final HashMap<String, String> hashMap = new HashMap<String, String>() {
        {
            put("foo", "foo1");
            put("bar", "bar1");
            put("car", "BMW");
            put("truck", "MAN");
        }
    };
    String res = replaceParams(hashMap, "This is '%(foo)' and '%(foo)', but also '%(bar)' '%(bar)' indeed.");
    System.out.println(res);
    System.out.println(replaceParams(hashMap, "This is '%(car)' and '%(foo)', but also '%(bar)' '%(bar)' indeed."));
    System.out.println(replaceParams(hashMap, "This is '%(car)' and '%(truck)', but also '%(foo)' '%(bar)' + '%(truck)' indeed."));
}

출력은 다음과 같습니다.

This is 'foo1' and 'foo1', but also 'bar1' 'bar1' indeed.
This is 'BMW' and 'foo1', but also 'bar1' 'bar1' indeed.
This is 'BMW' and 'MAN', but also 'foo1' 'bar1' + 'MAN' indeed.