Однострочник для обтекания текста списком чисел - PullRequest
0 голосов
/ 30 августа 2018

Предположим, у меня есть последовательность строк, которая выглядит примерно так:

1 10 46565 5968678 3 567 78

Я бы хотел превратить его в

F(1) F(10) F(46565) F(5968678) F(3) F(567) F(78)

Существует ли регулярное выражение с одной строкой, которое выполнит это в Stata с произвольным числом элементов?

Я пытался:

. display ustrregexra("1 10 46565 5968678 3 567 78","([:digit:]){1,}","XXX")
XXX XXX XXX XXX XXX XXX XXX

и

. display ustrregexra("1 10 46565 5968678 3 567 78","([:digit:]){1,}","F(&)")
F(&) F(&) F(&) F(&) F(&) F(&) F(&)

и

. display ustrregexra("1 10 46565 5968678 3 567 78","[0-9]{1,}","F(&)")
F(&) F(&) F(&) F(&) F(&) F(&) F(&)

В VI, похоже, это помогает:

.s/[0-9]\{1,}/F(&)/g

Есть ли эквивалент в Stata для функций юникода или ванильного регулярного выражения? Функции Stata ustrregex * основаны на механизме регулярных выражений ICU в соответствии с этим комментарием программиста StataCorp.

1 Ответ

0 голосов
/ 30 августа 2018

Здесь есть две проблемы:

  1. Stata не поддерживает регулярные выражения того типа, который вы упоминаете.
  2. Его функции регулярного выражения не могут обрабатывать подстановки, такие как F(\1).

Есть только один способ сделать это в одной (довольно длинной) строке:

clear
set obs 1

generate str = "1 10 46565 5968678 3 567 78"

local regex ([0-9]*)[ ]([0-9]*)[ ]([0-9]*)[ ]([0-9]*)[ ]([0-9]*)[ ]([0-9]*)[ ]([0-9]*)

generate new_str  = "F(" + regexs(1) + ") " + ///
                    "F(" + regexs(2) + ") " + ///
                    "F(" + regexs(3) + ") " + ///
                    "F(" + regexs(4) + ") " + ///
                    "F(" + regexs(5) + ") " + ///
                    "F(" + regexs(6) + ") " + ///
                    "F(" + regexs(7) + ")" if regexm(str, "`regex'")

. list, abbreviate(10)

     +--------------------------------------------------------------------------------+
     |                         str                                            new_str |
     |--------------------------------------------------------------------------------|
  1. | 1 10 46565 5968678 3 567 78   F(1) F(10) F(46565) F(5968678) F(3) F(567) F(78) |
     +--------------------------------------------------------------------------------+

Очевидно, вы можете обобщить это и сделать его «истинным» одним вкладышем, написав небольшую программу.


EDIT:

Ниже приведено обобщение, в котором также используется хитрость Роберта:

program define foo, rclass
local string `1'
local string = ustrregexra("`string'","\D"," ")
local string = ustrtrim(itrim("`string'"))
local string = ustrregexra("F("+"`string'"+")"," ", ") F(")
return local old_string `1'
return local new_string `string'
end

foo "1 10 46565 5968678 3 567 78"

return list

macros:
         r(new_string) : "F(1) F(10) F(46565) F(5968678) F(3) F(567) F(78)"
         r(old_string) : "1 10 46565 5968678 3 567 78"

foo "1xcvb10gh46565sdda5968678luiy3f567kl78"

return list

macros:
         r(new_string) : "F(1) F(10) F(46565) F(5968678) F(3) F(567) F(78)"
         r(old_string) : "1xcvb10gh46565sdda5968678luiy3f567kl78"
...