Operating System - Linux
1830354 Members
2304 Online
110001 Solutions
New Discussion

Re: Challenging Script question

 
SOLVED
Go to solution
Patrick Wallek
Honored Contributor

Re: Challenging Script question

Inserting into the middle is going to be a bit more difficult.

First you are going to have to calculate the "middle" of a file.

Say the file has 8 lines -- the middle would be after the 4th line (8 / 2 = 4)

Now the problem comes if the file has 9 lines (or any other odd number). What do you consider the middle? Since 9 / 2 = 4.5 do you truncate and insert after the 4th line or round up and insert after the 5th line?
Peter Nikitka
Honored Contributor

Re: Challenging Script question

Hi,

try this:

#!/bin/ksh
...
# $tempfile contains file to be injected
# $NF contains original file
typeset -i COUNT=`wc -l <$NF`
awk -v c=$((COUNT/2)) -v inj=$tempfile '{print}
NR==c {while ((getline
mfG Peter
The Universe is a pretty big place, it's bigger than anything anyone has ever dreamed of before. So if it's just us, seems like an awful waste of space, right? Jodie Foster in "Contact"
Peter Nikitka
Honored Contributor

Re: Challenging Script question

Hi,

posting missed a ')' in close(inj).
In a view of Patricks comment:
For a odd number N of lines, the text is inserted at (N-1)/2 .

Inserting at (N+1)/2 is left to the reader as an exercise...

#!/bin/ksh
...
# $tempfile contains file to be injected
# $NF contains original file
typeset -i COUNT=`wc -l <$NF`
awk -v c=$((COUNT/2)) -v inj=$tempfile '{print}
NR==c {while ((getline
mfG Peter
The Universe is a pretty big place, it's bigger than anything anyone has ever dreamed of before. So if it's just us, seems like an awful waste of space, right? Jodie Foster in "Contact"
Unix or Linux?
Frequent Advisor

Re: Challenging Script question

Just tried your code.
Im getting an error message when I try to run it.

It says:

$NF: ambiguous redirect
James R. Ferguson
Acclaimed Contributor

Re: Challenging Script question

Hi:

To insert in the middle of the file, this variation trades memory for I/O. THat is, the input file is read *once* into memory instead of twice, the first time to obtain the number of lines it contains.

The input file is updated "in-place", too:

cat .inject.pl
#!/usr/bin/perl
use strict;
my $i;
my $oldfile = pop;
my $newfile = "$oldfile.new";
open(FIN ,"<",$oldfile) or die "Can't open '$oldfile': $!\n";
open(FOUT,">",$newfile) or die "Can't open '$newfile': $!\n";
my @lines = ;
for ($i=0; $i < ($#lines/2); $i++) {print FOUT $lines[$i]};
print FOUT "@ARGV\n";
for ($i=$i; $i <= $#lines+1; $i++) {print FOUT $lines[$i]};
close FOUT;
rename($newfile, $oldfile);
1;

# ./inject.pl This is in the Middle! FileName

Regards!

...JRF...
Sandman!
Honored Contributor

Re: Challenging Script question

imho...the arithmetic operator in your script is errorneous i.e.

>> COUNT=`expr $COUNT \ 2`

I presume this is the expression you are using in your script and it is not simply a typo since the division operator is / not \. So change the above to:

COUNT=`expr $COUNT / 2`

Consider adding 1 to the line count before dividing since that's closer to the middle for odd-numbered lines which have no middle line i.e. 11/2=5.5. It will have no effect on even numbered lines since integer division truncates

COUNT=`cat $NF | wc -l`
let COUNT=COUNT+1
COUNT=`expr $COUNT / 2`

cheers!
Sandman!
Honored Contributor

Re: Challenging Script question

Ignore my last post as it's flawed. After a careful inspection of your posting here's the updated version of the shell script you should use:

#!/bin/sh

echo $* | awk '{
"wc -l <"$NF | getline cnt
mid=int((cnt+1)/2)
system("split -l "mid" "$NF)
for(i=1;i "tmpfile"
system("cat xaa tmpfile xab >"$NF)
}'
Unix or Linux?
Frequent Advisor

Re: Challenging Script question

Does the statement

"wc -l <"$NF | getline cnt

check the file for number of lines then pipe it to getline and then store it in cnt.
Have I got it right?
Sandman!
Honored Contributor

Re: Challenging Script question

The reason is that NF is an awk variable and it is not available for processing outside of the awk construct. Moreover adding a 1 to the line count causes file1 to be split into exactly two files xaa and xab, irrespective of odd or even number of lines in file1. If you don't add 1 to the line count then file1 will get split into >2 files and the cat (concatenate) command will fail to pick up the last one. Hope it makes sense!

:)
Unix or Linux?
Frequent Advisor

Re: Challenging Script question

Great thanks.

Im assuming that at the end of the script it would be appropriate to remove xaa and xab. Would it make a big difference if they were not removed?
Sandman!
Honored Contributor

Re: Challenging Script question

>Does the statement

>"wc -l <"$NF | getline cnt

>check the file for number of lines then pipe it to getline and then store it in cnt.
>Have I got it right?


Yes that is exactly right. Remember that NF is an awk variable and is not available for processing outside of the awk construct.

NF==number of fields
$NF==file1

cheers!
Sandman!
Honored Contributor

Re: Challenging Script question

>Great thanks.

>Im assuming that at the end of the script it would be appropriate to remove >xaa and xab. Would it make a big difference if they were not removed?


xaa and xab are temporay files created for the purpose of inserting a line in the middle of file1 and they can be removed at the end of the script. The "rm xaa xab" does not need to be inside the awk construct though i.e.

#!/bin/sh

echo $* | awk '{
"wc -l <"$NF | getline cnt
mid=int((cnt+1)/2)
system("split -l "mid" "$NF)
for(i=1;i "tmpfile"
system("cat xaa tmpfile xab >"$NF)
}'

rm xaa xab
Unix or Linux?
Frequent Advisor

Re: Challenging Script question

Thank you. Problem solved