명명 된 문자열 대체?


13

나는 종종 같은 문자열을 여러 번 대체해야합니다.

(format "%s %s %s" "a" "a" "a") ;; gives: "a a a"

(이것은 단지 더미 예제입니다.이 경우 공백으로 "a"를 붙이는 것이 좋지만 일반적으로 더 복잡한 상황을 처리합니다)

명명 된 대체 방법이 있습니까? 예를 들어 파이썬에서는 다음과 같이 작성합니다.

"{0} {0} {0}".format("a") # or:
"{name} {name} {name}".format(name="a")


@Malabarba는 : 나는 여기에 해당 스레드에서 어떤 대답의 수정 vestion을 게시 대답 .
Adobe

답변:


16

이 답변을 다시 쓰면 다른 해결책이 있습니다.

(format-spec "%a %a %a %b %b %b" (format-spec-make ?a "a" ?b "b"))

편집 : 다른 format-spec솔루션

Malabarba는 다음과 같이 의견을 제시합니다.

(format-spec "%a %a %a %b %b %b" '((?a . "a") (?b . "b")))

편집 2 : 대체 전 평가 :

다음은 대체 전에 평가 한 예입니다.

(let ( (a 1)
       (b 2) )
  (message (format-spec "a = %a; b = %b" (format-spec-make ?a a ?b b))) )
;; ⇒ a = 1; b = 1

(let ( (a 1)
       (b 2) )
  (message (format-spec "a = %a; b = %b" `((?a . ,a) (?b . ,b)))) )
;; ⇒ a = 1; b = 2

3
또한 그것은 format-spec-makealist 일뿐입니다 :'((?a . "a") (?b . "b"))
Malabarba

1
"숫자로 작동하지 않는 것 같습니다"– emacs.stackexchange.com/questions/7481/…
npostavs

@npostavs : 알아두면 좋습니다! 나는 대답을 편집했다.
Adobe

14

Magnar Sveen의 문자열 조작 라이브러리 s.el은이 를 수행하는 다양한 방법을 제공합니다. 예를 들면 다음과 같습니다.

(require 's)
(s-format "${name} ${name} ${name}" 'aget '(("name" . "test")))
;; ==> "test test test"

참고 s-format어떤 대체물 기능을하지만, 특별한 처리를 제공 할 수 있습니다 aget, elt하고 gethash. 따라서 다음과 같이 토큰 목록을 사용하고 색인별로 참조 할 수 있습니다.

(s-format "$0 $0 $0 $1 $1 $1" 'elt '("a" "b"))
;; ==> "a a a b b b"

범위 내 변수를 사용하여 다음과 같이 바꿀 수도 있습니다.

(let ((name "test"))
  (s-lex-format "${name} ${name} ${name}"))
;; ==> "test test test"

1
훌륭합니다.이 기능에 대해 몰랐습니다! 나는 대부분의 시간을 s.el을 사용하여 Emacs에서 일반적인 문자열 조작 작업을 수행하는 방법을 들여다 보았지만 이것은 실제로 기존 함수의 한 줄짜리 래퍼 이상입니다.
wasamasa

3

s.el의 s-lex-format은 실제로 원하는 것이지만 변수 이름뿐만 아니라 대체 블록 안에 코드를 실제로 넣으려면 개념 증명으로 이것을 썼습니다.

(defmacro fmt (str)
  "Elisp string interpolation for any expression."
  (let ((exprs nil))
    (with-temp-buffer
      (insert str)
      (goto-char 1)
      (while (re-search-forward "#{" nil t 1)
        (let ((here (point))
              (emptyp (eql (char-after) ?})))
          (unless  emptyp (push (read (buffer-substring (point) (progn (forward-sexp 1) (point)))) exprs))
          (delete-region (- here 2) (progn (search-forward "}") (point)))
          (unless emptyp (insert "%s"))
          (ignore-errors (forward-char 1))))
      (append (list 'format (buffer-string)) (reverse exprs)))))

;; demo with variable and code substitution 
(fmt "My name is #{user-full-name}, I am running Emacs #{(if (display-graphic-p) \"with a GUI\" \"in a terminal\")}.")
;; results in
"My name is Jordon Biondo, I am running Emacs with a GUI."

미쳤다면 fmt다른 사람 에게 전화를 걸 수도 있습니다.fmt

(fmt "#{(fmt\"#{(fmt\\\"#{user-full-name}\\\")}\")}")
;; =>
"Jordon Biondo"

코드는 format호출로 확장 되므로 모든 대체가 순서대로 수행되고 런타임에 평가됩니다.

(cl-prettyexpand '(fmt "Hello, I'm running Emacs #{emacs-version} on a #{system-type} machine with #{(length (window-list))} open windows."))

;; expands to

(format "Hello, I'm running Emacs %s on a %s machine with %s open windows."
        emacs-version
        system-type
        (length (window-list)))

항상 % s를 사용하는 대신 사용되는 형식 유형을 개선 할 수 있지만 런타임에 수행해야하고 오버 헤드를 추가해야하지만 모든 형식 인수를 함수 형식으로 둘러 싸서 수행 할 수 있습니다. 유형에 있지만 실제로 당신이 원할 수있는 유일한 시나리오는 아마 수레이며 심지어 대체에서 (형식 "% f"float)를 수행 할 수도 있습니다.

더 많이 연구하면이 대답 대신이 요점을 업데이트 할 가능성이 큽니다. https://gist.github.com/jordonbiondo/c4e22b4289be130bc59b


3

범용은 아니지만 사례를 해결합니다.

(apply 'format "%s %s %s" (make-list 3 'a))

제공된 예제 사용 :

(apply 'format (concat " * - :raw-html:`<img width=\"100%%\" "
                       "src=\"http://xxx.xxx/images/languages/"
                       "staff/%s.jpg\" alt=\"%s.jpg\"/>` - .. _%s:")
       (make-list 3 'some-image))

제공합니다 :

" * - :raw-html:`<img width=\"100%\" src=\"http://xxx.xxx/images/languages/staff/some-image.jpg\" alt=\"some-image.jpg\"/>` - .. _some-image:"

내가 다루는 샘플 문자열은 다음과 같습니다 " * - :raw-html:`<img width=\"100%%\" src=\"http://xxx.xxx/images/languages/staff/%s.jpg\" alt=\"%s.jpg\"/>` - .. _%s:".-모두 %s동일합니다.
Adobe

@Adobe 귀하의 예를 들어 답변을 업데이트했습니다.
wvxvw
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.