Using Cut with multiple delimeter

88 Views Asked by At

I have a small problem. I have a variableCTI_VARIABLES with this content:

cti_CallDirection=1@;cti_ContractNumber=00202417@;cti_TransferVDN=48195@;cti_IvrButton=1

Each different variable within this variable is marked “@;” separated by . I’m trying to separate them with the CUT() function. But it only returns the first one, because it accepts a single character as an argument. How can I do it when I want to separate by two characters?

Here is my dialplan code

exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})
same => n,GotoIf($["${CTI_VARIABLES}" = ""]?noVariables)
same => n,Set(TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,@\;)})
same => n,Set(COUNTER=1)
same => n,While($[${COUNTER} <= ${TOTAL_VARS}])
same => n,Set(CURRENT_VAR=${CUT(CTI_VARIABLES,@\;,${COUNTER})})
same => n,Set(VAR_NAME=${CUT(CURRENT_VAR,\=,1)})
same => n,Set(VAR_VALUE=${CUT(CURRENT_VAR,\=,2)})
same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${VAR_VALUE})
same => n,NoOp(${VAR_NAME}: ${VAR_VALUE})
same => n,Set(COUNTER=$[${COUNTER}+1])
same => n,EndWhile
same => n(noVariables),NoOp(No CTI Variables Set)

I also tried using the FIELDQTY() function with no luck:

TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,\@\;)}
TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,@;)}
3

There are 3 best solutions below

1
arheops On BEST ANSWER

Why you ever may need count something for this simple task?

So. Let me give you "the asterisk way":

; noop actually not needed, because MSet will show you all variables
exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})

same => n,Set(MVAR=${STRREPLACE(CTI_VARIABLES,@;,\,)}); replace all @; to comma
same => n,MSet(${MVAR}); put all names/vars on channel
; actually if you know variable names, you not need all below
; same=>n,Dumpchan();uncomment this if you want to see result.

same => n(loop),ExecIf($[ "${MVAR}" == "" ]?Return()); exit
same => n,Set(VAR=${CUT(MVAR,\,,1)}); get next one
same => n,Set(MVAR=${CUT(MVAR,\,,2-)}); put from second back in string
; at this moment VAR has variable name and MVAR have other pairs without ${VAR}=${${VAR}}
same => n,Set(VAR_NAME=${CUT(VAR,=,1)}); get only name

same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${${VAR_NAME}); catch it from channel and put in header
same => n,Goto(loop); next one

Thats ALL

Short tips WHY all those are working.

MSet syntax is like this

[Syntax]
MSet(name1=value1[,name2=value2[,...]])

And it will set all variables in one command

if you are using

 ${${VAR}}

asterisk will take value of variable VAR and put value of variable with that name.

If cut have no delimiter, and you asking for second param, it return empty string.

So ACTUALLY perfect way is return all info you need from your CURL request or AGI or whatever source of those variables in format like this

cti_CallDirection=1,cti_ContractNumber=00202417,cti_TransferVDN=48195,cti_IvrButton=1

After that make single MSet and put READABLE dialplan for headers.

2
Maftun Hashimli On

It appears that you are attempting to use the CUT function in your dialplan code to divide the variables within the CTI_VARIABLES string. yet the problem you have is that you have a two-character delimiter, "@;," yet CUT only allows one character as the delimiter. The REGEX function is used in the line CURRENT_VAR=${REGEX(${CTI_VARIABLES},([^@;]+)@;,,${COUNTER})} to extract each variable individually using the regex pattern ([^@;]+)@;. This pattern records one or more non-"@" or ";" characters, then follows them with "@;". One variable at a time is extracted in the while loop by using the ${COUNTER} option in the REGEX function. Setting the variable name, variable value, and adding them as PJSIP headers are done using the same code as before.

5
miken32 On

The easy answer is to fix your AGI to output something more useful. Asterisk's dialplan syntax is pretty terrible for doing any real programming tasks, and a good philosophy is to avoid doing anything in dialplan that you can do elsewhere. Ideally in this case, you'd be populating individual variables with values.

But if that is not an option, then just replace the @; sequence with a single character before processing it.

STRREPLACE(CTI_VARIABLES,@;,;)

Now you can use CUT() on the semicolon.

Full diaplan (untested)

exten => addheader,1,NoOp(CTI_VARIABLES: ${CTI_VARIABLES})
same => n,GotoIf($["${CTI_VARIABLES}" = ""]?noVariables)
same => n,Set(CTI_VARIABLES=${STRREPLACE(CTI_VARIABLES,@;,;)})
same => n,Set(TOTAL_VARS=${FIELDQTY(CTI_VARIABLES,;)})
same => n,Set(COUNTER=1)
same => n,While($[${COUNTER} <= ${TOTAL_VARS}])
same => n,Set(CURRENT_VAR=${CUT(CTI_VARIABLES,;,${COUNTER})})
same => n,Set(VAR_NAME=${CUT(CURRENT_VAR,=,1)})
same => n,Set(VAR_VALUE=${CUT(CURRENT_VAR,=,2)})
same => n,Set(PJSIP_HEADER(add,${VAR_NAME})=${VAR_VALUE})
same => n,NoOp(${VAR_NAME}: ${VAR_VALUE})
same => n,Set(COUNTER=$[${COUNTER}+1])
same => n,EndWhile
same => n(noVariables),NoOp(No CTI Variables Set)

Note you shouldn't need to do any escaping unless you're dealing with commas; Asterisk's argument parsing is pretty basic.