New to Kotlin, I'd like to insert a line in the file after a specific match in the file. I know how to do this with sed like the following:
sed "/some line in file/a some text I'd like to add after line" file
But I'd like to understand how I'd go about this in Kotlin. So far I've got got as far as the printWriter interface, but I don't see anything that clearly implies an offset or regex parameter.
So far I've got:
File("file.txt").printWriter(...)
Thanks!
GNU 'sed' does not insert/remove/update lines in files, it transforms an input stream and provides options for sending the output stream to stdout, to a file, or even to a temporary file which then overwrites the original file after the transformation is complete (this is the --in-place option).
Here is some code that should get you started but note that there are lots of ways to buffer and read/write files, streams, etc.
val file = File("file.txt")
val tempFile = createTempFile()
val regex = Regex("""some line in file""")
tempFile.printWriter().use { writer ->
file.forEachLine { line ->
writer.println(when {
regex.matches(line) -> "a some text I'd like to add after line"
else -> line
})
}
}
check(file.delete() && tempFile.renameTo(file)) { "failed to replace file" }
See also sed, a stream editor for more details on how it transforms text streams.
Related
I am fairly new to progress 4gl. I am trying to copy the contents of one df file into another file where I want to copy everything except the areas of the df file. this is what I have so far.
define stream mystream.
input from "C:\OpenEdge\WRK\df file\sample.df".
do while true on endkey undo, leave:
output to "C:\OpenEdge\WRK\df file\test1.df".
end.
output close.
display "finished".
I would first like to copy all the contents of the first df file into another df file, but right now I'm getting a blank file. Please let me know where I am going wrong.
This is what I do:
grep -v AREA < dbname.df > dbname.df2
If you are stuck with on OS that lacks "grep" or if you just have an urge to do it with 4gl code I'd do something like:
define variable lineIn as character no-undo.
input from "dbname.df".
output to "dbname.df2".
repeat:
import unformatted lineIn. /* read the data a whole line at a time */
if lineIn begins " AREA" then next. /* skip lines that start with " AREA" */
put unformatted lineIn skip. /* spit the input line back out */
if lineIn = "" then put unformatted skip(1). /* yes, this is a weird thing */
end.
To copy all the contents of first df file to another df file, use this code:
DEFINE VARIABLE TEXT-STRING AS CHARACTER FORMAT "X(76)".
INPUT FROM "C:\OPENEDGE\WRK\CMD-LOG.DF".
OUTPUT TO "C:\OPENEDGE\WRK\MY.DF".
DO WHILE TRUE ON ENDKEY UNDO, LEAVE:
IMPORT UNFORMATTED TEXT-STRING.
MESSAGE TEXT-STRING .
END.
INPUT CLOSE.
OUTPUT CLOSE.
I want to read and write the same file simultaneously. Here is a simplified code:
clc;
close all;
clearvars;
fd = fopen ('abcd.txt','r+'); %opening file abcd.txt given below
while ~feof(fd)
nline = fgetl(fd);
find1 = strfind(nline,'abcd'); %searching for matching string
chk1 = isempty(find1);
if(chk1==0)
write = '0000'; %in this case, matching pattern found
% then replace that line by 0000
fprintf(fd,'%s \n',write);
else
continue;
end
end
File abcd.txt
abcde
abcd23
abcd2
abcd355
abcd65
I want to find text abcd in string of each line and replace the entire line by 0000. However, there is no change in the text file abcd.txt. The program doesn't write anything in the text file.
Someone can say read each line and write a separate text file line by line. However, there is a problem in this approach. In the original problem, instead of finding matching text `abcd, there is array of string with thousands of elements. In that case, I want to read the file, parse the file for find matching string, replace string as per condition, go to next iteration to search next matching string and so on. So in this approach, line by line reading original file and simultaneously writing another file does not work.
Another approach can be reading the entire file in memory, replacing the string and iterate. But I am not very sure how will it work. Another issue is memory usage.
Any comments?
What you are attempting to do is not possible in a efficient way. Replacing abcde with 0000, which should be done for the first line, would require all remaining text forward because you remove one char.
Instead solve this reading one file and write to a second, then remove the original file and rename the new one.
I have the following problem: when I try to save the file that contains a semicolon in the name it returns a huge and weird stacktrace of the characters on the page. I've tried to escape, to trim and to replace those semicolons, but the result is still the same. I use the following regex:
$value =~ s/([^a-zA-Z0-9_\-.]|;)/uc sprintf("%%%02x",ord($1))/eg;
(I've even added the |; part separately..)
So, when I open the file to write and call the print function it returns lots of weird stuff, like that:
PK!}�3y�[Content_Types].xml ���/�h9\�?�0���cz��:� �s_����o���>�T�� (it is a huge one, this is just a part of it).
Is there any way I could avoid this?
Thank you in advance!
EDIT:
Just interested - what is the PK responsible of in this string? I mean I can understand that those chars are just contents of the file, but what is PK ? And why does it show the content type?
EDIT 2.0:
I'm uploading the .docx file - when the name doesn't contain the semicolon it works all fine. This is the code for the file saving:
open (QSTR,">", "$dest_file") or die "can't open output file: $qstring_file";
print QSTR $value;
close (QSTR);
EDIT 3.0
This is a .cgi script, that is called after posting some data to the server. It has to save some info about the uploading file to a temp file (name, contents, size) in the manner of key-value pairs. So any file that contains the semicolon causes this error.
EDIT 4.0
Found the cause:
The CGI param function while uploading the params counts semicolon as the delimiter! Is there any way to escape it in the file header?
The PK in file header it means it is compressed ZIP like file, like docx.
One guess: The ; is not valid character in filename at the destination?
Your regexp is not good: (the dot alone is applicable to any character...)
$value =~ s/([^a-zA-Z0-9_\-.]|;)/uc sprintf("%%%02x",ord($1))/eg;
Try this:
#replace evey non valid char to underscore
$value =~ s/([^a-zA-Z0-9_\-\.\;])/_/g;
I am writing a script that can execute a batch file, which needs to open a file in the same folder first. My current code is:
from subprocess import Popen
p = Popen("Mad8dl.bat <RUNTHISTO.txt>", cwd=r"C:\...\test")
stdout, stderr = p.communicate()
where the ... is just the path to the folder. However, everytime I run it I get the syntax error:
The syntax of the command is incorrect
Any help regarding the syntax would be greatly appreciated.
First, you should probably remove the < and > angle brackets from your code; just pass the filename, without any brackets, to your batch file. (Unless your filename really does contain < and > characters, in which case I really want to know how you managed it since those characters are forbidden in filenames in Windows).
Second, your code should look like:
from subprocess import Popen, PIPE
p = Popen(["Mad8dl.bat", "RUNTHISTOO.txt"], cwd=r"C:\...\test", stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
Note the list containing the components of the call, rather than a single string. Also note that you need to specify stdout=PIPE and stderr=PIPE in your Popen() call if you want to use communicate() later on.
I wish to read in a text file and print it verbatim in a knitr doc. I got some code to read a text file into a string:
filename = 'foo.txt'
text = readChar(filename, file.info(filename)$size)
However, my every attempt to print out the text results in ugly craziness. Using print() does not wrap the lines. It leaves "## [1]" all over the output. Using results='asis' doesn't do what I want. Trying \verbatim and \spverbatim doesn't do the right thing.
What is the easy way out here?
I got this to work with
\begin{spverbatim}
\Sexpr{text}
\end{spverbatim}
not in a knitr block.