2010-05-06 2 views
3

Я использую функцию reReplace() ColdFusion для замены регулярных выражений.ColdFusion - обратный вызов regex для вызова функции

Я хотел бы использовать вызов функции для строки замены и передать ему согласованную обратную ссылку.

Что-то вроде этого:

<cfset s = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" /> 
<cfset s = reReplace(s, "STARTDATE_([\s-.:0-9]*)_ENDDATE", dateAdd("h", 1, "\1")) /> 

Но это не удается, потому что «значение параметра 3, который в настоящее время \ 1, должно быть значение класса java.util.Date.»

Есть ли другой способ достичь этого?

Спасибо, Stu

+0

Заметка о том, почему это не работает: CF передает оценку регулярного выражения на движок Java, который ожидает строки для параметров. Поэтому CF попытается оценить все в строке до того, как это произойдет. Мы все хотим, чтобы вы могли передавать функции, но это не работает. Однако у Гари есть правильная идея. –

+0

Ага - интересный материал. Я думаю, это все, что я действительно хотел узнать, но я не могу отметить комментарий как принятый ответ :-) – stubotnik

ответ

2

Я не слишком уверен, что то, что вы хотите сделать, возможно с помощью подхода, описанного в вашем примере, но вот схема другого подхода, который должен работать.

  1. вычистить строки даты
  2. Convert это жало в объект времени с помощью CreateDateTime
  3. Выполнять любые операции даты на этом объекте, т.е. DATEADD
  4. Преобразовать обратно в строку, используя DateFormat
  5. Проделайте замените

При использовании встроенных функций даты и времени ColdFusion мне нравится всегда следить за тем, чтобы я проходил дату/ti me скорее, чем строка даты/времени для параметров, для которых требуется объект даты/времени. Это потому, что ColdFusion может интерпретировать строки как месяцы или наоборот.

+0

Вы, вероятно, хотите parseDate() вместо createDateTime(), но в противном случае на деньги. –

+0

Привет, Гари. Я надеялся избежать этой дороги по соображениям производительности (см. Комментарий к ответе Андреаса), но похоже, что у меня нет альтернативы. Принимая это как ответ - cheers – stubotnik

0

Насколько я могу видеть из вашего примера кода, вы хотите заменить всю строку с датой один час позже, чем показано в строке. Так как возникают проблемы с reReplace, я попытался бы удалить нефиксированную часть строки, используя функции replace() или replaceNoCase().

<cfset s = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" /> 
<cfset s = replaceNoCase(replaceNoCase(s, "STARTDATE_", ""),"_ENDDATE","")> 
<cfoutput> 
    <cfif isDate(s)> 
     before: #s# after: #dateAdd("h", 1, s)# 
    </cfif> 
</cfoutput> 

DATEADD() требует действительной даты в качестве параметра, я не думаю, что вы можете сделать это с помощью регулярных выражений, который будет обратной ссылкой ВСЕГДА быть строкой.

+0

Привет Андреас - спасибо за ответ. Пример был упрощен для объяснения моей проблемы. То, что мне действительно нужно сделать, - это заменить несколько вхождений дат, встроенных в большой текстовый документ. Так что просто извлечение даты не работает для меня. И повторные вызовы reFind с returnubexpressions = true, а вызов replace на каждом матче слишком медленный ... Спасибо в любом случае! – stubotnik

1

У меня есть утилита, которая позволяет вам достичь того, чего вы хотите.

Синтаксис не совсем такой же, и немного раздражает «простые» вещи, но в конечном итоге он более гибкий.

В основном вы пишете функцию, которая принимает строку Match и массив Groups и возвращает строку - внутри функции вы можете делать то, что вам нравится, и она будет применяться к каждому совпадению.

Как так:

<cfset Jrex = createObject('component','jre-utils').init() /> 


<cfset MyString = "STARTDATE_2010-05-07 00:05:00.0_ENDDATE" /> 
<cfset MyRegex = "STARTDATE_([\s-.:0-9]*)_ENDDATE" /> 
<cfset MyString = Jrex.replace(MyString , MyRegex , addHour , 'all')/> 


<cffunction name="addHour" returntype="String" output="false"> 
    <cfargument name="Match" type="String"/> 
    <cfargument name="Groups" type="Array" default="#ArrayNew(1)#"/> 

    <cfset var Result = DateAdd('h',1,Groups[1]) /> 

    <cfreturn DateFormat(Result , 'yyyy-mm-dd') 
     & ' ' & TimeFormat(Result , 'HH:mm:ss') 
     /> 
</cffunction> 


Детали и скачать здесь: http://www.hybridchill.com/projects/jre-utils.html

Одна вещь, чтобы иметь в виду, что это использует java.util.regex двигатель, который отличается от CF's org.apache.oro.text.regex, и, хотя это обеспечивает больше возможностей, fe w ничего не работает (пока).

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

В частности, одна функциональность я размышлял, как избежать ручной функции метод многословно обратного вызова, как описано выше - возможно, позволяя что-то вроде этого:

Jrex.replace(MyString , MyRegex , "\F:DateAdd('h',1,\1)" , 'all') 

Было бы хорошо, чтобы услышать, если кто-то имеет мысли об этом.

+0

Hi Peter - пример не удался для меня с «Метод appendReplacement не был найден». Но в противном случае это выглядит точно так же, как я надеялся. Благодаря! – stubotnik

+0

Привет, stubotnik, это немного странно, метод appendReplacement является частью Java и существует с версии 1.4 (а с тех пор как CF работает раньше 1.4), можете ли вы подтвердить, с какими CF и Java-версиями вы работаете? –

+0

CF 9 и Java 1.6.0_14. «метод не найден» бросается, когда CF имеет проблемы с литьем переменных и вычисляет правильный перегруженный метод для использования. Может, в этом и проблема? – stubotnik

Смежные вопросы