Extract a string in terraform - terraform

I have the following string value that comes from a YAML file. I want to extract the first two parts of the string within the terraform file. Let me know how it can be done. I tried the split function.
String: "sg:dev:crm"
Expected value: "sg:dev"
Tried: split(":","sg:dev:crm")[1,2] // This doesn't work

You would have to split it into two separate values and concatenate them. For example:
locals {
sg = "sg:dev:crm"
split_sg = split(":","sg:dev:crm")
wanted_str = "${local.split_sg[0]}:${local.split_sg[1]}"
}
Also, you tried referencing wrong indexes after you split the string because indexes start from 0, and sg is at index 0 while dev is at index 1.

Related

How to import variable labels from Excel into Stata

I have a Excel-sheet, which contains variable and variable-labels. I would like to import this file into Stata. How can I do it?
Let's assume that your variable names are on the first row, and labels on the second row.
I would do:
import excel using file.xlsx, firstrow clear
foreach var of varlist _all {
local x = `var'[1]
label var `var' "`x'"
}
drop if [_n]==1
foreach var of varlist _all {
cap destring `var', replace
}
The first bit replaces the label of the variables with the variable label, which should be in the first row of your imported dataset. The second bit drops this row, and the destrings all variables for which this is possible without an error. The reason for this is that all variables will be imported as strings when you have the second row as variable labels.
This is the most typical case I encountered, but of course there may be other scenarios where you have to adopt different approaches.

Kusto query language split # character and take last item

If I have a string for example:
"this.is.a.string.and.I.need.the.last.part"
I am trying to get the last part of the string after the last ".", which in this case is "part"
How to I achieve this?
One way I tried was to split the string on ".", I get a array back, but then I don't know how to retrieve the last item in the array.
| extend ToSplitstring = split("this.is.a.string.and.I.need.the.last.part", ".")
gives me:
["this", "is","a","string","and","I","need","the","last", "part"]
and a second try I have tried this:
| extend ToSubstring = substring(myString, lastindexof(myString, ".")+1)
but Kusto do not have a function of lastindexof.
Anyone with tips?
you can access the last member of the array using a negative index -1.
e.g. this:
print split("this.is.a.string.and.I.need.the.last.part", ".")[-1]
returns a single table, with a single column and a single record, with the value part
You can try the code below, and feel free to change it to meet your need:
let lastIndexof = (input:string, lookup: string) {
indexof(input, lookup, 0, -1, countof(input,lookup))
};
your_table_name
| extend ToSubstring = substring("this.is.a.string.and.I.need.the.last.part", lastIndexof("this.is.a.string.and.I.need.the.last.part", ".")+1)

How can I use a specified order of strings to index from a cell array?

I am trying to index from a cell aray of a number of potential reference files to use for a comparison. The comparison files have distinct parts of their file names that I'd like to use to specify a single reference file.
However, I'm only able to return reference files that contain the three distinct parts, in any order. How can I enforce the order?
Example:
The comparison file is:
deg_baseFileName = "Test1_female_44k_70dBA_babble7ch_1sp_20k_00dBA_48k"
I use strsplit to break the filename into parts:
deg_parts = strsplit(deg_baseFileName, "_");
The distinguishing parts are:
deg_parts(2), deg_parts(4), deg_parts(8)
In this case: "female", "70dBA", "00dBA" - in that order.
I use these functions to identify and index with the distinguishing parts:
strToFind = {string(deg_parts(2)),string(deg_parts(4)),string(deg_parts(8))}'; % Strings to match
fun = #(s)~cellfun('isempty',strfind(ref_files,s));
out = cellfun(fun,strToFind,'UniformOutput',false);
idx = all(horzcat(out{:}),2);
However, the index returns two values from my reference file cell array:
Ref_female_44k_00dBA_babble7ch_1sp_20k_70dBA_48k.wav
Ref_female_44k_70dBA_babble7ch_1sp_20k_00dBA_48k.wav
Both contain the distinguishing parts, but only the second in the correct order.
Is there a way I can enforce the order in my out call?
Thanks!
In the simplest case, where the comparison and reference files only differ in their first part, you can use strrep:
refFile = strrep(deg_baseFileName, 'Test1', 'Ref');
If you know what the other parts of the file name will be, and they are the same for all the reference files but differ from the comparison file, you can just use sprintf to create your file name:
refFile = sprintf('Ref_%s_44k_%s_babble7ch_1sp_20k_%s_48k.wav', ...
deg_parts(2), deg_parts(4), deg_parts(8));
If you don't know or care what the other parts could be, you can generalize the above to create a match expression for use with regexp to find the index of reference files with the correct order:
expr = sprintf('Ref_%s_[^_]+_%s_[^_]+_[^_]+_[^_]+_%s_[^_]+.wav', ...
deg_parts(2), deg_parts(4), deg_parts(8));
index = ~cellfun('isempty', regexp(ref_files, expr));

count occurrences of a string in a structure

I have a structure mydata and I need to access one of its fields mydata.myfield, and within that field, access another field mydata.myfield.mysecondfield. In the last field, mydata.myfield.mysecondfield I need to check how many times a particular string ('apple') occurs.
I have tried with:
aaa=unique(mydata.myfield.mysecondfield,'apple')
bbb=cellfun(#(x) sum(ismember(mydata.myfield.mysecondfield,x)),aaa,'un',0)
but I get this error: Attempt to reference field of non-structure array.
The structure contains fields with both strings and numeric values.
The underlying problem may be due to the fact that the structure is a little bit different from how you describe it. Following your question, I created it as follows:
mydata = struct();
mydata.myfield.mysecondfield = {'apple' 'apple' 'orange' 'banana' 'apple' 'kiwi'};
and since I'm not getting the same error you get, I think the underlying types may be slightly mismatching. Anyway, given mydata defined as above, if you change your code as follows, it should work but it will return the count of every unique occurrence within the field:
aaa = unique(mydata.myfield.mysecondfield);
bbb = cellfun(#(x) sum(ismember(mydata.myfield.mysecondfield,x)),aaa,'un',0)
bbb =
4×1 cell array
[3]
[1]
[1]
[1]
If you only want to count the number of apple occurrences, you should use the following approach instead:
apple_count = sum(strcmp(mydata.myfield.mysecondfield,'apple')); % 3

How to check if string contains a substring in terraform interpolation?

How do you check if a terraform string contains another string?
For example, I want to treat terraform workspaces with "tmp" in the name specially (e.g. allowing rds instances to be deleted without a snapshot), so something like this:
locals
{
is_tmp = "${"tmp" in terraform.workspace}"
}
As far as I can tell, the substr interpolation function doesn't accomplish this.
For terraform 0.12.xx apparently you are suppose to use regexall to do this.
From the manual for terraform 0.12.XX:
regexall() documentation
regexall can also be used to test whether a particular string matches a given pattern, by testing whether the length of the resulting list of matches is greater than zero.
Example from the manual:
> length(regexall("[a-z]+", "1234abcd5678efgh9"))
2
> length(regexall("[a-z]+", "123456789")) > 0
false
Example applied to your case in terraform 0.12.xx syntax should be something like:
locals
{
is_tmp = length(regexall(".*tmp.*", terraform.workspace)) > 0
}
It also specifically says in the manual not to use "regex" but instead use regexall.
If the given pattern does not match at all, the regex raises an error. To test whether a given pattern matches a string, use regexall and test that the result has length greater than zero.
As stated above this is because you will actually get an exception error when you try to use it in the later versions of 0.12.xx that are out now when you run plan. This is how I found this out and why I posted the new answer back here.
You can indirectly check for substrings using replace, e.g.
locals
{
is_tmp = "${replace(terraform.workspace, "tmp", "") != terraform.workspace}"
}
Like #MechaStorm, with Terrafor 0.12.7+ you can use regex to return a Boolean value if your string contains a particular substring
locals {
is_tmp = contains(regex("^(?:.*(tmp))?.*$",terraform.workspace),"tmp")
}
The regex query returns a list of capture groups for any characters before tmp, tmp if found, any characters after tmp. Then contains looks for "tmp" in the list and returns true or false. I am using this type of logic in my own terraform.
Length of the list produced by split function is greater than one when separtor is a substring.
locals {
is_tmp = length(split("tmp", terraform.workspace)) > 1
}
Use replace( string, search, replace ) as in the snippet:
// string contains ABBA = result is ABBA
output "match" {
value = "${ replace("xxxABBAyyy", "/(?:.*)(ABBA)(?:.*)/", "$1") }"
}
// string doesn't contain ABBA = result is original string
output "no_match" {
value = "${ replace("xxxBABAyyy", "/(?:.*)(ABBA)(?:.*)/", "$1")}"
}
// string contains ABBA (ingorecase) = result is AbBA
output "equals_ignorecase" {
value = "${ replace("xxxAbBAyyy", "/(?:.*)((?i)ABBA)(?:.*)/", "$1")}"
}
An output of terraform apply is:
Outputs:
equals_ignorecase = AbBA
match = ABBA
no_match = xxxBABAyyy
In terraform 0.12.7, we now have regex . This may help simplify some code and make it readable to some (perhaps?)
> regex("[a-z]+", "53453453.345345aaabbbccc23454")
aaabbbccc
I use this way to check if bucket name start with test-tmp
eg. test-tmp, test-tmp-app1, test-tmp-db1 etc..
is_test_bucket = can(regex("^(test-tmp){1}($|-{1}.*$)", var.bucket_name))
Something that makes sense reading, IMHO:
locals {
is_tmp = can(regex("tmp", terraform.workspace))
}
This works because the regex function will raise an error if no matches are found.
Bonus: since Terraform 1.3.x, there are the new startswith and endswith functions that can be handy in a good amount of cases.

Resources