I have started programming in csh just a while ago, and I am having one specific problem.
I have an external input file with the structure:
[division]
[[subdivision1]]
vara = value1
varb = value2
[[subdivision2]]
anothername = value3
I would like to extract the values "value1", "value2", etc, and set them as variables from this format. I know how to read lines, but not how to specify that the variable I want is just "valuei", after the "= ", not the whole line itself.
Edited to add that I know that I can read line by line and then splitting by delimiters, but I was wondering if there was a cleaner way.
How could I do it?
Thanks
foreach over a list of words is the most idiomatic csh way of looping, and this can be used to advantage. The following shows how to use this, with a little state included to check when we have found the tokens var, = and value.
set prev =
foreach word (`cat data`)
if ( "$prev" == "=" ) then
echo "found var $var = $word"
endif
set var = "$prev"
set prev = "$word"
end
will produce
found var vara = value1
found var varb = value2
found var anothername = value3
which is reasonably clean. The disadvantage is that you can't choose how csh splits your words. Thus, if your values contain whitespace there is not really much you can do.
Related
I'm trying to split a variable based on the type of characters.
I need this:
var = "word12345-54321" #No spaces to help out.
to turn into this:
var2 = "word"
var3 = "12345"
var4 = "54321"
I'm able to extract the word with regex, but I can't find a way to separate the numbers.
As you're already using a RegEx I'd suggest using a pattern like (\D*)(\d*)-(\d*) if the strings will always be in a LETTERSNUMBERS-NUMBERS format.
I am presently working on a file to open one by one .txt documents, extract data, to finally fill a .excel document.
Because I did not know how it is possible to write multiple times on the same line of my Excel document after one write statement (because it jumps to the next line), I have created a string of characters which is filled time after time :
Data (data_limite(x),x=1,8)/10, 9, 10, 7, 9, 8, 8, 9/
do file_descr = 1,nombre_fichier,1
taille_data1 = data_limite(file_descr)
nvari = taille_data1-7
write (new_data1,"(A30,A3,A11,A3,F5.1,A3,A7,F4.1,<nvari>(A3))") description,char(9),'T-isotherme',char(9),T_trait,char(9),'d_gamma',taille_Gam,(char(9),i=1,nvari)
ecriture_descr = ecriture_descr//new_data1
end do
Main issue was I want to adapt char(9) amount with the data_limite value so I built a write statement with a variable amount of char(9).
At the end of the do-loop, I have a very complex format of ecriture_descr which has no periodic format due to the change of the nvari value
Now I want to add this to the first line of my .excel :
Open(Unit= 20 ,File='resultats.RES',status='replace')
write(20,100) 'param',char(9),char(9),char(9),char(9),char(9),'*',char(9),'nuances',char(9),'*',char(9),ecriture_descr
100 format (a5,5(a3),a,a3,a7,a,a3,???)
but I do not know how to write this format. It would have been easier if, at each iteration of the do-loop I could fill the first line of my excel and continue to fill the first line at each new new_data1 value.
EDIT : maybe adding advance='no' in my write statement would help me, I am presently trying to add it
EDIT 2 : it did not work with advance='no' but adding a '$' at the end of my format write statement disable the return of my function. By moving it to my do-loop, I guess I can solve my problem :). I am presently trying to add it
First of all, your line
ecriture_descr = ecriture_descr//new_data1
Is almost certainly not doing what you expect it to do. I assume that both ecriture_descr and new_data are of type CHARACTER(len=<some value>) -- that is a fixed length string. If you assign anything to such a string, the string is cut to length (if the assigned is too long), or padded with spaces (if the assigned is too short:
program strings
implicit none
character(len=8) :: h
h = "Hello"
print *, "|" // h // "|" ! Prints "|Hello |"
h = "Hello World"
print *, "|" // h // "|" ! Prints "|Hello Wo|"
end program strings
And this combination will work against you: ecriture_descr will already be padded to the max with spaces, so when you append new_data1 it will be just outside the range of ecriture_descr, a bit like this:
h = "Hello" ! h is actually "Hello "
h = h // "World" ! equiv to h = "Hello " // "World"
! = "Hello World"
! ^^^^^^^^^
! Only this is assigned to h => no change
If you want a string aggregator, you need to use the trim function which removes all trailing spaces:
h = trim(h) // " World"
Secondly, if you want to write to a file, but don't want to have a newline, you can add the option advance='no' into the write statement:
do i = 1, 100
write(*, '(I4)', advance='no') i
end do
This should make your job a lot easier than to create one very long string in memory and then write it all out in one go.
I want to pass an empty string as one of the values to a bash for-loop – like this:
for var in "" A B C; do
...
done
This works. However, I would like to store the possible values in a variable, like this:
VARS="" A B C
for var in $VARS; do
...
Here, the empty string is ignored (or all values are concatenated if I use for var in "$VARS"). Is there an easy way to solve this?
You can't. Don't do that. Use an array.
This is a version of Bash FAQ 050.
VARS=("" A B C)
for var in "${VARS[#]}"; do
: ...
done
And you almost never want to use an unquoted variable (like for var in $VARS).
I would suggest using an array
#!/bin/bash
array=("" 1 2 "")
for i in "${array[#]}";do
echo $i
done
I have variable1 with strings such as "asdfsad What do you do", "qwer What is your name", "Zebra"
And variable2 with strings "asdfsad", "qwer", "Animal"
I want to remove the first word from the strings in variable1 if it equals the word in variable2. The only thing I can come up with so far is to replace each word separately:
i.e. variable1=tranwrd(variable1, "asdfsad", ""); etc. however I have many words to replace.
Many thanks for your help.
How about something like this:
data sample;
length variable1 variable2 $100;
variable1= "asdfsad What do you do"; variable2 = "asdfsad"; output;
variable1= "qwer What is your name"; variable2 = "qwer"; output;
variable1= "Zebra" ; variable2 = "Animal"; output;
run;
data fixed;
length first_word $100;
set sample;
first_word = scan(variable1,1);
if first_word eq variable2 then do;
start_pos = length(first_word) + 1;
variable1 = substr(variable1,start_pos);
end;
run;
This will work for matching on the entire first word. It leaves the spaces or other punctuation in the remaining text but you should be able to change that easily if you like.
If your problem is to match character-by-character and not on the entire first word then that would be a very different question and I would recommend posting a new question.
If you are happy with the results from tranwrd, you can use that too. You just need to be careful of whitespace
variable1 = strip(tranwrd(variable1, strip(variable2), ''));
if scan(variable1,1)=variable2 then
variable1=substr(variable1,index(variable1," "));
This is probably not going to be efficient or feasible for thousands of words, but you could use a Perl regular expression (e.g. s/search/replacement/) via prxchange
/* words to match delimited by "|" */
%let words = asdfsad|qwer|Animal|foo|bar|horse;
/* example data */
data example;
infile datalines dlm=',' dsd;
input string: $256.;
datalines;
asdfsad What do you do
qwer What is your name
Zebra
food is in the fridge
foo A horse entered a bar
;
run;
/* cleaned data */
data example_clean;
set example;
/*
regular expression is:
- created once on first row (_n_ = 1)
- cached (retain regex)
- dropped at the end (drop regex).
*/
if _n_ = 1 then do;
retain regex;
drop regex;
regex = prxparse("s/^(&words)\s+//");
end;
string = prxchange(regex, 1, string); /* apply the regex (once) */
run;
The ^ symbol in the regular expression (constructed in prxparse) ensures that it matches only at the start of the word, the | symbols make it an 'or' match and the \s+ matches one or more whitespace characters (which is why in my example, "food" is not matched).
I'm trying to find the locations where a substring occurs in a cell array in MATLAB. The code below works, but is rather ugly. It seems to me there should be an easier solution.
cellArray = [{'these'} 'are' 'some' 'nicewords' 'and' 'some' 'morewords'];
wordPlaces = cellfun(#length,strfind(cellArray,'words'));
wordPlaces = find(wordPlaces); % Word places is the locations.
cellArray(wordPlaces);
This is similar to, but not the same as this and this.
The thing to do is to encapsulate this idea as a function. Either inline:
substrmatch = #(x,y) ~cellfun(#isempty,strfind(y,x))
findmatching = #(x,y) y(substrmatch(x,y))
Or contained in two m-files:
function idx = substrmatch(word,cellarray)
idx = ~cellfun(#isempty,strfind(word,cellarray))
and
function newcell = findmatching(word,oldcell)
newcell = oldcell(substrmatch(word,oldcell))
So now you can just type
>> findmatching('words',cellArray)
ans =
'nicewords' 'morewords'
I don't know if you would consider it a simpler solution than yours, but regular expressions are a very good general-purpose utility I often use for searching strings. One way to extract the cells from cellArray that contains words with 'words' in them is as follows:
>> matches = regexp(cellArray,'^.*words.*$','match'); %# Extract the matches
>> matches = [matches{:}] %# Remove empty cells
matches =
'nicewords' 'morewords'