In older versions of MATLAB(e.g. 2015b), we can simply use
['aa','bb','cc']
to join 3 strings into one, 'aabbcc'.
But in 2019b, I find the result of
["aa","bb","cc"]
would be
ans =
1×3 string array
"aa" "bb" "cc"
, and it tells me I should use the join function to do the trick.
It seems a new feature, which is totally fine with me. However, when I found that I need to develop code in 2019b in my laptop, and our remote server uses 2015b, it comes to a disaster. I am wondering if there is some way to do the same job, i.e. get "aabbcc" in the example, and could be recognized by both 2015b & 2019b?
There is a difference between an array of chars '' and a real string "". This explicit difference was introduced in 2017a:
string Arrays: Create string arrays using double quotes
You can create strings using double quotes, just as you can create
character vectors with single quotes.
str = "Hello, World" creates a string.
str = ["Good" "morning"] creates a 1-by-2 string array.
For more information, see Characters and Strings.
To get the same functionality as the well-known char arrays, you should substitute the concatenating [] with strcat() and to get the number of characters (independently whether it is a string or a char-array) by strlen() (because length("Hello") yields 1 but strlen("Hello") yields 5).
Related
Context
I am designing a code that runs a bunch of calculations, and outputs figures. At the end of the code, I want to save everything in a nice way, so my take on this is to go to a user specified Output directory, create a new folder and then run the save process.
Question(s)
My question is twofold:
I want my folder name to be unique. I was thinking about getting the current date and time and creating a unique name from this and the input filename. This works but it generates folder names that are a bit cryptic. Is there some good practice / convention I have not heard of to do that?
When I get the datetime string (tn = datestr(now);), it looks like that:
tn =
'07-Jul-2022 09:28:54'
To convert it to a nice filename, i replace the '-',' ' and ':' characters by underscores and append it to a shorter version of the input filename chosen by the user. I do that using strrep:
tn = strrep(tn,'-','_');
tn = strrep(tn,' ','_');
tn = strrep(tn,':','_');
This is fine but it bugs me to have to use 3 lines of code to do so. Is there a nice one liner to do that? More generally, is there a way to look for every non letter or number character in a string and replace it with a given character? I bet that's what regexp is there for but frankly I can't quite get a hold on how regexps work.
Your point (1) is opinion based so you might get a variety of answers, but I think a common convention is to at least start the name with a reverse-order date string so that sorting alphabetically is the same as sorting chronologically (i.e. yymmddHHMMSS).
To answer your main question directly, you can use the built-in makeValidName utility which is designed for making valid variable names, but works for making similarly "plain" file names.
str = '07-Jul-2022 09:28:54';
str = matlab.lang.makeValidName(str)
% str = 'x07_Jul_202209_28_54'
Because a valid variable can't start with a number, it prefixes an x - you could avoid this by manually prefixing something more descriptive first.
This option is a bit more simple than working out the regex, although that would be another option which isn't too nasty here using regexprep and replacing non-alphanumeric chars with an underscore:
str = regexprep( str, '\W', '_' ); % \W (capital W) matches all non-alphanumeric chars
% str = '07_Jul_2022_09_28_54'
To answer indirectly with a different approach, a nice trick with datestr which gets around this issue and addresses point (1) in one hit is to use the following syntax:
str = datestr( now(), 30 );
% str = '20220707T094214'
The 30 input (from the docs) gives you an ISO standardised string to the nearest second in reverse-order:
'yyyymmddTHHMMSS' (ISO 8601)
(note the T in the middle isn't a placeholder for some time measurement, it remains a literal letter T to split the date and time parts).
I normally use your folder naming approach with a meaningful prefix, replacing ':' by something else:
folder_name = ['results_' strrep(datestr(now), ':', '.')];
As for your second question, you can use isstrprop:
folder_name(~isstrprop(folder_name, 'alphanum')) = '_';
Or if you want more control on the allowed characters you can use good old ismember:
folder_name(~ismember(folder_name, ['0':'9' 'a':'z' 'A':'Z'])) = '_';
I am trying to write a Powershell code to identify a string with a specific character from a filename from multiple files.
An example of a filename
20190902091031_202401192_50760_54206_6401.pdf
$Variable = $Filename.Substring(15,9)
Results:
202401192 (this is what I am after)
However in some instances the filename will be like below
20190902091031_20240119_50760_54206_6401.pdf
$Variable = $Filename.Substring(15,9)
Results:
20240119_ (this is NOT what I am after)
I am trying to find a code to identify the 9th character,
IF the 9th character = "_"
THEN Set
$Variable = $Filename.Substring(15,8)
Results:
20240119
All credit to TheMadTechnician who beat me to the punch with this answer.
To expand on the technique a bit, use the split method or operator to split a string every time a certain character shows up. Your data is separated by the underscore character, so is a perfect example of using this technique. By using either of the following:
$FileName.Split('_')
$FileName -split '_'
You can turn your long string into an array of shorter strings, each containing one of the parts of your original string. Since you want the 2nd one, you use the array descriptor [1] (0 is 1st) and you're done.
Good luck
I have a line saved as $variable1, for example:
file"yourtxthere/i/master.ext" autostart:true, width
How would I go about writing the correct syntax using Regex in Powershell to grab everything within the quotes. Are regular expressions the best way to do this in Powershell?
Though regular expressions are powerful, this is a simple case. Thus a simple solution is based on string object's split() method.
$variable1 = 'file"yourtxthere/i/master.ext" autostart:true, width'
# Splitting requires at least one "
if ($variable1.IndexOf('"') -gt 0) {
$variable1.Split('"')[1]
}
Splitting the string will result an array of three elements:
file
yourtxthere/i/master.ext
autostart:true, width
As Powershell's arrays begin with index zero, the desired data is at index location 1. In case the string doesn't contain a double quote, the split won't work. This is checked with the statement
if ($variable1.IndexOf('"') -gt 0)
Without one, splitting a quoteless string would return just a one-celled array and trying to access index 1 would result in an error message:
$variable1.Split('!')[1]
Index was outside the bounds of the array.
I'm not 100% sure I understand the question but assuming you had that stored in $variable1 as a string like so:
$variable1 = 'file"yourtxthere/i/master.ext" autostart:true, width'
Then you could extract just the quoted text by splitting the string using the double quotes as a delimiter like this:
$variable1.Split('"')[1]
That splits the string into an array with three parts. The first part is everything before the first double quotes and the second everything in between the first and second quote marks, and the third everything after the second quotation marks. The [1] tells it to output the second part.
I think this picture might illustrate it a little better.
There are other ways to split that up and in fact the variable isn't necessary at all if you do something like this:
('file"yourtxthere/i/master.ext" autostart:true, width').split('"')[1]
That will work fine so long as there are never any extra double quotes before the first occurrence.
[23567,0,0,0,0,0] and other value is [452221,0,0,0,0,0] and the value should be contineously displaying about 100 values and then i want to display only the sensor value like in first sample 23567 and in second sample 452221 , only the these values have to display . For that I have written a code
value = str2double(str(2:7));see here my attempt
so I want to find the comma in the output and only display the value before first comma
As proposed in a comment by excaza, MATLAB has dedicated functions, such as sscanf for such purposes.
sscanf(str,'[%d')
which matches but ignores the first [, and returns the next (i.e. the first) number as a double variable, and not as a string.
Still, I like the idea of using regular expressions to match the numbers. Instead of matching all zeros and commas, and replacing them by '' as proposed by Sardar_Usama, I would suggest directly matching the numbers using regexp.
You can return all numbers in str (still as string!) with
nums = regexp(str,'\d*','match')
and convert the first number to a double variable with
str2double(nums{1})
To match only the first number in str, we can use the regexp
nums = regexp(str,'[(\d*),','tokens')
which finds a [, then takes an arbitrary number of decimals (0-9), and stops when it finds a ,. By enclosing the \d* in brackets, only the parts in brackets are returned, i.e. only the numbers without [ and ,.
Final Note: if you continue working with strings, you could/should consider the regexp solution. If you convert it to a double anyways, using sscanf is probably faster and easier.
You can use regexprep as follows:
str='[23567,0,0,0,0,0]' ;
required=regexprep(str(2:end-1),',0','')
%Taking str(2:end-1) to exclude brackets, and then removing all ,0
If there can be values other than 0 after , , you can use the following more general approach instead:
required=regexprep(str(2:end-1),',[-+]?\d*\.?\d*','')
I'm facing a problem with string in MATLAB the default string is C:\Users\Root\Downloads\Path. I want to make this string with single quotes inside it like this 'C:\Users\Root\Downloads\Path\'. I try many times to escape the string with backslash like other programming languages but MATLAB didn't doing this i don't know how to fix this problem.
Code:
clear all
clc
s='C:\Users\Root\Downloads\Path';
str=fprintf('%s',s);
The trick is to use two quotes instead of one:
s='''C:\Users\Root\Downloads\Path''';
str=fprintf('%s',s)
'C:\Users\Root\Downloads\Path'
str =
30
Note that str will be the number 30, since fprintf returns the number of characters it prints, not the string itself! If you just want the string, then the first line is enough.
disp(s)
'C:\Users\Root\Downloads\Path'
Note that there is no data type "String" in MATLAB. You have an array of characters.