how to change multiple items in a text file?
2 次查看(过去 30 天)
显示 更早的评论
Idin Pushkin
2019-5-3
hello
i have a text file with name of bp. u see many 'TSTEP' in this file. there are other written text just below them like: '1*100'. now i want to find these 'TSTEP's and make changes on the text below them (just changing the number before the asterisk). for example '1*100' is going to be '2.5*100' or any other number can be replaced. i use this code when i have one 'TSTEP' in file. ut it doesnt work for the cases when there are more than one of it. the number of TSTEPs may differ from file to file. is it possible to do that?
thanks in advance
clc;
fid=fopen('bp.txt','r');
c=textscan(fid,'%s','delimiter','\n','Whitespace','','CommentStyle','1','CollectOutput',0);
fclose(fid);
c=string(c{:})
iz=find(contains(c,"TSTEP"));
d1=['2.5','*',extractAfter(c{iz+1},'*')];
d2=replace(c,c{iz+1},d1);
fid = fopen('bp.txt','w');
for j= 1:length(d2)
fprintf(fid, '%s\n', char(d2{j}));
end
fclose(fid);
采纳的回答
Stephen23
2019-5-3
编辑:Stephen23
2019-5-7
EDIT: much faster:
rpl = '2.5'; % the new value (you can generate this using NUM2STR).
str = fileread('bp.txt');
str = strtrim(regexp(str,'\n','split'));
idx = 1+find(strcmpi(str,'TSTEP'));
str(idx) = regexprep(str(idx),'^[^*]+',rpl);
fid = fopen('pb_new.txt','wt');
fprintf(fid,'%s\n',str{:});
fclose(fid);
rpl = '2.5'; % the new value (you can generate this using NUM2STR).
rgx = '(?<=\s+TSTEP\s+)\d+(?=\*100)'; % regular expression.
% Read old file and replace data:
old = fileread('bp.txt');
new = regexprep(old,rgx,rpl);
% Save the new file:
fid = fopen('bp_new.txt','wb');
fprintf(fid,'%s',new);
fclose(fid)
The input and output files are attached.
23 个评论
Idin Pushkin
2019-5-3
'100' under TSTEP can take a value from natural numbers (not just 100, can be 1, 2 ,3 or any other number). this number or any number in that place remains unchanged. i want to change the number before '*', the first number.
Stephen23
2019-5-3
编辑:Stephen23
2019-5-3
"'100' under TSTEP can take a value from natural numbers (not just 100, can be 1, 2 ,3 or any other number)."
It is very easy to adjust the regular expression to match any integer:
rgx = '(?<=\s+TSTEP\s+)\d+(?=\*\d+)'; % regular expression.
% ^^^ matches any integer
The rest of the code remains the same.
Idin Pushkin
2019-5-3
at first it worked but now it doesnt work again. the final code which i used was:
rpl = '3'; % the new value (you can generate this using NUM2STR).
rgx = '(?<=\s+TSTEP\s+)\d+(?=\*\d+)'; % regular expression.
% Read old file and replace data:
old = fileread('bp.txt');
new = regexprep(old,rgx,rpl);
% Save the new file:
fid = fopen('bp.txt','wb');
fprintf(fid,'%s',new);
fclose(fid)
i want to overwrite the new data to old file.
Stephen23
2019-5-4
编辑:Stephen23
2019-5-4
"at first it worked"
That is great, I am very happy for you.
"but now it doesnt work again"
I have no idea what "it doesn't work" actually means. If you did not explain what it is actually happening, then I do not know: is the code running, or does it stop with an error? (if so, what error message?) Does a file get created, or no file? Do you get the the expect values in the file, or are the new values incorrect? Does nothing happen? Or do you get an infinite loop and your laptop catches fire?
When you explain what occurs then it helps me to understand what is happening, which means that I can help you to fix it. Writing "it doesn't work" tells me nothing, because I have no idea what you expect and what is actually happening.
"i want to overwrite the new data to old file."
I suspect that that overwriting might be related to your problem: once you have overwritten that file once, what do you expect to change the next time? (hint: nothing).
Idin Pushkin
2019-5-4
this the final code you offered:
rpl = '3'; % the new value (you can generate this using NUM2STR).
rgx = '(?<=\s+TSTEP\s+)\d+(?=\*\d+)'; % regular expression.
% Read old file and replace data:
old = fileread('bp.txt');
new = regexprep(old,rgx,rpl);
% Save the new file:
fid = fopen('bp.txt','wb');
fprintf(fid,'%s',new);
fclose(fid)
the code is running but, nothing happens. i mean it does not change the wanted line. either for one 'TSTEP' or more than one. for cases which have more than one 'TSTEP' it takes a bit longer than expected time to run. u can test it.
Stephen23
2019-5-4
编辑:Stephen23
2019-5-4
"u can test it. "
I doubt that the letter "u" can test it.
"the code is running but, nothing happens"
When I ran the code that you gave on your example file from your question and it worked correctly: every single TSTEP '1' was replaced by '3'. I have attached the code that I used (copied from your last comment) and the output file (which is simply the input file overwritten).
So far it all seems to be working exactly as expected.
Are you trying to run this code multiple times on the same file?
Has the file format changed? (please upload the file you are testing it on).
"it takes a bit longer than expected time to run"
That regular expression will not be particularly fast: I designed it for simplicity of the replacement string, rather than for speed.
Idin Pushkin
2019-5-4
编辑:Idin Pushkin
2019-5-4
"Are you trying to run this code multiple times on the same file?"
yes.
For the first run it changed the wanted lines but, for the following multiple times (just testing) it doesnt change anything and remains unchanged and gives:
"ans=0"
Stephen23
2019-5-4
编辑:Stephen23
2019-5-4
"For the first run it changed the wanted lines but, for the following multiple times (just teting) it doesnt change anything"
Of course, what do you expect to happen? By overwriting that file, this is what you are doing:
- replace '1' with '3'
- replace '3' with '3'
- replace '3' with '3'
- replace '3' with '3'
- etc.
After the first run, nothing will "change" when you simply view the file (in fact the characters are being changed, because it changes '3' for '3', just as you are requesting it to do!).
So on the first run you changed all the '1' to '3'. After that, what do you expect to happen with the overwritten file that already contains '3' ?
Idin Pushkin
2019-5-4
编辑:Idin Pushkin
2019-5-4
consider this:
- at first i replace '3' with '9'.
- then replace '9' with another number. for example; '10'.
and this continues. For first running of the code i used '2.5' for the attached file and it worked perfecty. Then i wanted to replace '2.5' with '5'. it didnt work and gives " ans=0".
Stephen23
2019-5-4
编辑:Stephen23
2019-5-4
"consider this:"
- "at first i replace '3' with '9'."
- "then replace '9' with another number. for example; '10'."
Well that is certainly not what you originally requested in your question, but it is easy enough to do in a loop. Just put my answer inside a loop and on each loop iteration change the rpl character vector to whatever number you want it ito be:
vec = [3,9,10];
for k = 1:numel(vec)
rpl = num2str(vec(k));
... the rest of my code
end
That is exactly why I made the rpl simple: so that you could change it easily yourself.
Stephen23
2019-5-5
编辑:Stephen23
2019-5-5
@Idin Pushkin: it worked correctly when I tried it: the code replaced '1' with '6', exactly as I would expect (the code file and output file are attached). I have no idea what else you expect to happen, because you did not explain what you expected to happen. Your comment "does not change" means nothing because you did not give any explanation what the input file contained, or what you expected the output file to be.
Note that the ans value your screenshot shows is simply because you did not put a semi-colon after fclose, it is basically unrelated to the contents of the file. But its zero value tells us that fclose successfully closed the file, which means that it was also successfully opened the file and successfully wrote data to the file.
So far everything you have shown indicates that every is working exactly as expected.
Idin Pushkin
2019-5-5
ok. i think it is needed to explain much more and what happens when i run the code;
consider the new attached file 'c.txt'.
this is one part of it which i want to change it:
'TSTEP
2.5*100 /'.
'100' is constant. i want to change '2.5'. this number is going to be replaced by other number as i explained. suppose it is '40'. so when the code ran the selected parts should be as follow:
'TSTEP
40*100 /'
OR generally
'TSTEP
'my number'*100'.
their might be one or more 'TSTEP' in file.
vec = 6;
for k = 1:numel(vec)
rpl = num2str(vec(k));
rgx = '(?<=\s+TSTEP\s+)\d+(?=\*\d+)'; % regular expression.
% Read old file and replace data:
old = fileread('bp.txt');
new = regexprep(old,rgx,rpl);
% Save the new file:
fid = fopen('bp.txt','wb');
fprintf(fid,'%s',new);
fclose(fid);
end
when the above code in run, no error is given but, it does not replace the number before '*' with new number. the other point is it is too slow. is there anyway to make it more fast?
Stephen23
2019-5-6
编辑:Stephen23
2019-5-7
"when the above code in run, no error is given but, it does not replace the number before '*' with new number."
I would not expect MATLAB to change anything in "c.txt", because that is not the filename that you have used in your code. Your example file is named "c.txt", and your code is reading and writing to "bp.txt".
When I changed your code to read "c.txt" and write "d.txt" it worked perfectly (the input file "c.txt", the output "d.txt", and code file "bp0.m" are all attached). So far the code works exactly as expected, and has changed the file values correctly every time that I have run it.
"the other point is it is too slow. is there anyway to make it more fast?"
Of course! The advantage of my original answer is that the file does not change any other characters (e.g. same newline characters). But you can considerably speed up the code if that is not a requirement. You will find that this is a lot faster:
rpl = '6'; % the new value (you can generate this using NUM2STR).
str = fileread('c.txt');
str = strtrim(regexp(str,'\n','split'));
idx = 1+find(strcmpi(str,'TSTEP'));
str(idx) = regexprep(str(idx),'^[^*]+',rpl);
fid = fopen('e.txt','wt');
fprintf(fid,'%s\n',str{:});
fclose(fid);
Once again I tested this to make sure that it works (the input file "c.txt", the output "e.txt", and code file "bp1.m" are all attached)
Idin Pushkin
2019-5-6
is there any way to write the original file on itself with this code? this code works perfectly but the output file name is different from the original one and i want to be the same.
in this code:
rpl = '6'; % the new value (you can generate this using NUM2STR).
str = fileread('c.txt');
str = strtrim(regexp(str,'\n','split'));
idx = 1+find(strcmpi(str,'TSTEP'));
str(idx) = regexprep(str(idx),'^[^*]',rpl);
fid = fopen('e.txt','wt');
fprintf(fid,'%s\n',str{:});
fclose(fid);
i want to overwrite the output file on the original file so i changed 'e.txt' to 'c.txt', every time i run the code with different 'rp1', and it is seen that:
'80*100 /' 'rp1=7' it becomes '70*100'
'70*100 /' 'rp1=12' it becomes '120*100'
what i want to say is it overwrites some part of new number on old number when input and output files have the same name. but for cases with different names of input and output file name it works correctly.
i want the output file has the same name as the input file.
Idin Pushkin
2019-5-8
i have another question. if we have something this line in that fie: '10*100'.
is it possible to time another number to '10' and replace it instead in the original line? for example im going to time 8 by 10 which makes 80. so in the original file we have '80*100'. i use this version of ur code
rpl = '15'; % the new value (you can generate this using NUM2STR).
str = fileread('FAR.DATA');
str = strtrim(regexp(str,'\n','split'));
idx = 1+find(strcmpi(str,'TSTEP'));
str1=extractBefore(str(idx),'*');
str2=cell2mat(str1)
str3=num2str(str2*rpl);
str(idx) = regexprep(str(idx),'^[^*]+',str3);
fid = fopen('FAR.DATA','wb');
fprintf(fid,'%s\n',str{:});
fclose(fid);
but it writes long cector before '*100' like:
...2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401 2401*100 /
????
how can i do that?
Idin Pushkin
2019-5-9
编辑:Idin Pushkin
2019-5-9
i use this code for indexing:
rpl = '8'; % the new value (you can generate this using NUM2STR).
str = fileread('bp.txt');
str = strtrim(regexp(str,'\n','split'));
idx = 1+find(strcmpi(str,'TSTEP'));
str1 = extractBefore(str(idx),'*');
for i=1:length(str1)
str2 = num2str(str2double(cell2mat(str1(i)))*str2double(rpl))
end
str(idx) = regexprep(str(idx),'^[^*]+',str2);
fid = fopen('bp.txt','wb');
fprintf(fid,'%s\n',str{:});
fclose(fid);
there may be different numbers before '*' for exampe:
'x*100 /' or 'y*100 /'. i want to replace 'x' by 'x*rpl' because 'x' may differ from one to other 'TSTEP', but it gets those numbers and multipies all of them to the last str2 of the loop.
Stephen23
2019-5-9
编辑:Stephen23
2019-5-9
str = fileread('bp.txt','r');
% ^^^^ What is this supposed to do?
I cannot find any indication in the documentation that fileread accepts two input arguments.
That loop serves absolutely no purpose: you simply generate and discard str2 multiple times, but keep only the final str2 value. You can also get rid of the cell2mat here:
str2double(cell2mat(str1(i)))
str2double(str1(i)) % simpler and more efficient
Most likely that entire calculation can be done without a loop anyway:
vec = str2double(str1) .* str2double(rpl)
"there may be different numbers before '*' ..."
Previously you indicated that you wanted to use one new value to replace all TSTEP old values: doing so is easy using the code that I have given you. However if you want each TSTEP old value to be replaced with its own special value then using a loop is probably simplest (with indexing into the vectors idx and vec).
Idin Pushkin
2019-5-9
编辑:Idin Pushkin
2019-5-9
str = fileread('bp.txt');
% ^^^^ What is this supposed to do?
it was spelling mistake about the above code. about the loop u said i use this code and doesnt work again
for i=1:length(vec)
str(idx) = regexprep(str(idx),'^[^*]+',num2str(vec(i)));
fid = fopen(newStr1,'wb');
fprintf(fid,'%s\n',str{:});
fclose(fid);
end
Stephen23
2019-5-10
I wrote "with indexing into the vectors idx and vec..."
You are using i with vec (which is good) and ignored idx (which is not good).
You can see that the elements of idx correspond to the elements of vec... therefore if you use indexing into vec then you will also need exactly the same indexing into idx (just as I wrote in my comment).
Note the putting the file writing code inside that loop just overwrites the file contents on each iteration. In the end, only the last iteration will remain, so there is no point in this being isnide the loop (apart from slowing down your code and heating up your room).
更多回答(1 个)
KSSV
2019-5-3
编辑:KSSV
2019-5-3
fid = fopen('data.txt','r') ;
S = textscan(fid,'%s','delimiter','\n') ;
fclose(fid) ;
S = S{1} ;
% Get indices Tsteps
idx = find(contains(S,'TSTEP'))+1 ;
% Replace the number
S1 = S ;
S1(idx) = {'2.5*100'} ;
% Write to file
fid = fopen('test.txt','w') ;
fprintf(fid,'%s\n',S1{:});
fclose(fid);
NOTE: If contains is not available, you can use strcmp, ismember.
8 个评论
Idin Pushkin
2019-5-3
编辑:Idin Pushkin
2019-5-3
ther is another point. in the line after Tsteps i want to extract the text after '*'. for example in '2.5*100 /' i want to extract '100 /' but with extraxtAfter it gives error.
extractAfter(S{idx},'*')
it is true for both cases whether we have one or more
Idin Pushkin
2019-5-3
编辑:Idin Pushkin
2019-5-3
it gives 'too many input arguments'
when there is one TSTEP it works finely, but for more than one idx it gives the error mentioned above.
Idin Pushkin
2019-5-3
thanks, it works. as the last question, continuing that part i use this line of code to join them and make them 1*1cell but it becomes 1*2.
d=[{'2.5*'},extractAfter(S(idx),'*')]
Walter Roberson
2019-5-3
Your idx is non-scalar because you have multiple matches in the file. extractAfter needs to return multiple values.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Matrix Indexing 的更多信息
标签
尚未输入任何标签。
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)