Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: Changing string in specific line/position in a file

by kcott (Archbishop)
on Nov 01, 2022 at 01:13 UTC ( [id://11147885]=note: print w/replies, xml ) Need Help??


in reply to Changing string in specific line/position in a file

G'day onemojofilter,

Your data contains four types of whitespace (assuming your alignment uses tabs). These are difficult to differentiate on a webpage. I've used `cat -vet` which shows: a tab as ^I; a form feed as ^L; a newline as $; and, a space as itself.

I created the following test data (working.txt) which has examples of the different types of whitespace. I added an additional page so you now have a "^LH" following both an "H" and a "^LH". I removed much of the original data and replaced the rest with text intended to explain each line. I believe this is still representative of what you originally showed.

$ cat -vet working.txt H$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Iswap1$ ...$ source for^Ireplace1$ ...$ ^LH$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Iswap2$ ...$ source for^Ireplace2$ ...$ ^LH$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Iswap3$ ...$ source for^Ireplace3$ ...$

I then ran this code:

#!/usr/bin/env perl use strict; use warnings; use autodie; use constant { CHANGE_LINE => 4, SOURCE_LINE => 6, PAGE_SEP => "\n\fH\n", }; use File::Copy 'copy'; my $work_file = 'working.txt'; my $bu_file = 'working.txt.bu'; copy($work_file, $bu_file) or die "Can't 'copy($work_file, $bu_file)': $!"; { open my $in_fh, '<', $bu_file; open my $out_fh, '>', $work_file; local $/ = PAGE_SEP; while (<$in_fh>) { chomp; my @lines = split /\n/; my ($change_line, $source_line) = (CHANGE_LINE, SOURCE_LINE); ++$change_line, ++$source_line if $. == 1; my ($replace) = $lines[$source_line] =~ /(\S+)$/; $lines[$change_line] =~ s/\S+$/$replace/; print $out_fh join("\n", @lines), (eof($in_fh) ? "\n" : PAGE_SEP); } }

Here's the result:

$ cat -vet working.txt H$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Ireplace1$ ...$ source for^Ireplace1$ ...$ ^LH$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Ireplace2$ ...$ source for^Ireplace2$ ...$ ^LH$ after 1 space$ after 2 spaces$ no leading spaces$ text^I^Ifollowed by 2 tabs$ target for^Ireplace3$ ...$ source for^Ireplace3$ ...$

Note that all of the original whitespace is retained unaltered. I do recommend you make a backup; doing this within the code is easiest and won't be forgotten.

Your initial text positions were incorrect. "25 through 35" covers 11 characters, but "20221103" is only 8 characters. Also, I made the starting position 23 not 25, and that assumes that all of the preceding whitespace was actually spaces; if some, or all, were tabs, that would be a different number. Tabs are just a single character:

$ perl -E 'my $x = "|\t|"; say $x; say length $x;' | | 3

If the situation is more complex than suggested in your OP, let Perl do the counting for you. Bear in mind that your character positions may start at 1 (1st char. is at pos. 1) but Perl will count from zero. I've no idea what you might need, but this should give you some hints:

$ perl -E ' my $x = "PROMPT\t\tTO CHANGE"; my $len = length $x; my $from_index = rindex($x, "\t") + 1; my $from_pos = $from_index + 1; say $x; say "$from_pos through $len"; say substr $x, $from_index, $len - $from_index; say substr $x, $from_index; ' PROMPT TO CHANGE 9 through 17 TO CHANGE TO CHANGE

— Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11147885]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-19 04:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found