How to add lines into text file

Posted on 2009-07-14
Last Modified: 2012-05-07
Hi, all,
I tried to insert lines and text strings into a text file using Tie::File, but had run into several obstacles. Your help is greatly appreciated!
1) the splice line of my code has caused "bad file descriptor error on my ../Tie/
2) I had hard time to find a solution that will find the dynamic line number for the seesion footer, i.e. the "Subtotal"s, which should be the next line after the  50/51...runs.
To describe the steps involved:
1) based on the first two numbers of the 2nd column, if = 50, then Salaries, if =51 then Operating...
2) insert a line before the 50 session with the label of 'Salaries' or 'Operating'... and
3) add a label on the session footer line as subtotal...
Btw, I have full control of the creation of the input file. In another words, I could make it comma delimited or tab delimited or fixed position, so the regular expression could find them.
Also, since the file is likely smaller than 1 mg, and the script will only be called occassionaly, I don't mind to have a solution that doesn't use Tie::File.

Here is the simplified input file
-----  ------ -----
xyz    50100   $100
yyy    50200  $1000
zzz    50300
abc    51200  
bbbb   51300  $123

and here is the output/modified file
-----  ------ -----
Salaries                               #<--inserted session header line
xyz    50100   $100
yyy    50200  $1000
zzz    50300      
  Subtotal Salaries $1100  #<--insterted session footer label
Operating                          #<--inserted session header line
abc    51200  
bbbb   51300  $123
  Subtotal operating $123 #<--insterted session footer label

use Tie::File;
tie(@lines, 'Tie::File', $myfile) or die "Could not open $myfile: $!\n";
if($#lines == -1) {
    print "File is empty!\n";
else {
   if (substr($_,5,2  =='50' ){
          my $new_line ="Salaries";
          splice @lines, $.+1, 0, $new_line; }
    elseif(substr($_,5,2  =='51' ){
          my $new_line ="Operating";
          splice @lines, $.+1, 0, $new_line; }<--then insert a line above it
         <--then add the same label to the end of the session
print $_."\n";   

Open in new window

Question by:ommer
  • 2
  • 2
LVL 39

Accepted Solution

Adam314 earned 200 total points
ID: 24853560
Call by giving the input and output filenames on the command line.

eg: input.txt output.txt

use strict;
use warnings;
use Data::Dumper;
die "Usage: $0 <input> <output>\n" unless $#ARGV==1;
my $input = shift;
my $output = shift;
open(my $in, "<$input") or die "Could not open '$input': $!\n";
open(my $out, ">$output") or die "Could not open '$output': $!\n";
my $state;
while(<$in>) {
	if(/\S+\s+(\d{2})/ and !defined($state)) {
		if($1 eq '50') {
			$state = 'Salaries';
		elsif($1 eq '51') {
			$state = 'Operating';
		print $out "$state\n";
	elsif(/^\s+\$\d+\s*$/ and $state) {
		s/(.*)/  Subtotal $state $1/;
		$state = undef;
	print $out $_;

Open in new window


Author Comment

ID: 24854004
Great! It works flawlessly against my test data.

However, could you give me a little more explanations on next two lines, so when I apply it to the production data, I can make right adjustments?

if(/\S+\s+(\d{2})/ and !defined($state))  

elsif(/^\s+\$\d+\s*$/ and $state)
LVL 39

Expert Comment

ID: 24854310
if(/\S+\s+(\d{2})/ and !defined($state))
If the line matches the pattern:
    \S+         1 or more non-whitespace characters
    \s+          1 or more whitespace
    (...)         Save what is in the parenthesis to the $1 variable
    \d{2}      2 digits
And the $state hasn't yet been defined (meaning, this is the first line of a new session)

elsif(/^\s+\$\d+\s*$/ and $state)
If the line matches the pattern:
    ^             start of line
    \s+          1 or more whitespace
    \$            A dollar sign.  The $ is a special character, the backslash mean an actual dollar sign
    \d+         1 or more digits
    \s*          0 or more whitespace
    $             end of line
And $state is set (meaning, the session header has been printed, it contains the session name)

Author Closing Comment

ID: 31603429

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many situations when we need to display the data in sorted order. For example: Student details by name or by rank or by total marks etc. If you are working on data driven based projects then you will use sorting techniques very frequently.…
In the distant past (last year) I hacked together a little toy that would allow a couple of Manager types to query, preview, and extract data from a number of MongoDB instances, to their tool of choice: Excel (…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question