LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-05-2006, 02:16 PM   #1
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Rep: Reputation: 15
A newbie function question...


I'm writing a very simple package management script for use with CLFS which I won't explain the details of it but I need to make some modifications to the output of "du" and then flip the output upside down. I have made my modifications, I just need to flip the output of du upside down (so the first line would be last and the last line would be first).

I decided to use an existing gnu script and insert it as a function named "reverse". When I call this function with the command "reverse <FILENAME>" it outputs the contents of the file flipped. This is what I want it to do. But if I use the command "cat <FILENAME> | reverse" it outputs "bash - file-name". How would I modify this script so that it can use a pipe correctly?

Any help would be appreciated. Also, feel free to explain how the below function works if you feel like it.

Code:
function reverse
{
	FILE="$1"
	if [ $# -eq 0 ]; then
	  echo "$(basename $0) - file-name"
	  exit 1
	fi

	textArray[0]="" # hold text
	c=0 # counter
	# read whole file in loop
	while read line
	do
	  textArray[c]=$line # store line
	  c=$(expr $c + 1) # increase counter by 1
	done < $FILE
	# get length of array
	len=$(expr $c - 1 )

	# use for loop to reverse the array
	for (( i=$len; i>=0; i-- ));
	do
	  echo ${textArray[$i]}
	done
}

Last edited by fatsheep; 11-05-2006 at 02:43 PM.
 
Old 11-05-2006, 02:42 PM   #2
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
There is already a command to do this: rev.

As for your script, you are explicity testing for an argument (which will be absent when reading from stdin):

Code:
if [ $# -eq 0 ]; then
  echo "$(basename $0) - file-name"
  exit 1
fi
I don't use bash, so I'm not sure how best to differentiate between the filename and stdin. Zsh can reverse the file with a one-liner,

Code:
print -l ${(fOa)"$(<file)"}
 
Old 11-05-2006, 03:01 PM   #3
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by soggycornflake
There is already a command to do this: rev.

As for your script, you are explicity testing for an argument (which will be absent when reading from stdin):

Code:
if [ $# -eq 0 ]; then
  echo "$(basename $0) - file-name"
  exit 1
fi
I don't use bash, so I'm not sure how best to differentiate between the filename and stdin. Zsh can reverse the file with a one-liner,

Code:
print -l ${(fOa)"$(<file)"}
Thanks for the reply but rev doesn't do what I want. I only want the order of the lines reversed, not the lines themselves. For example, if I have a file with these contents:

Quote:
Line 1
Line 2
Line 3
Then after I apply the reverse function I get

Quote:
Line 3
Line 2
Line 1
Which is what I want. The rev command would give me:

Quote:
3 eniL
2 eniL
1 eniL
 
Old 11-05-2006, 03:34 PM   #4
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Oops, sorry, I mis-grepped the meaning of rev.
 
Old 11-05-2006, 03:50 PM   #5
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Anyway, the zsh snippet I gave should work:

Code:
#!/bin/zsh

if [[ -n $1 ]]; then
        print -l ${(fOa)"$(<$1)"}
else
        array=()
        while read line; do
                array+=$line
        done
        print -l ${(Oa)array}
fi
If you must use bash, you might need to duplicate the while loop and wrap it in an if test:

e.g.

Code:
if [[ -n $1 ]]; then
        while read line
        do
          textArray[c]="$line" # store line
          let "c+=1"
        done < $1
else    
        while read line
        do
          textArray[c]="$line" # store line
          let "c+=1"
        done
fi
Note that I replaced 'c=$(expr $c - 1 )' with the simpler 'let "c+=1"'. And, of course, remove the if test on $# at the start.

Last edited by soggycornflake; 11-05-2006 at 03:58 PM.
 
Old 11-05-2006, 03:56 PM   #6
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
Or use sed, example given with "info sed" :
Code:
#!/usr/bin/sed -nf
    
# reverse all lines of input, i.e. first line became last, ...
     
# from the second line, the buffer (which contains all previous lines)
# is *appended* to current line, so, the order will be reversed
1! G
     
# on the last line we're done -- print everything
$ p
     
# store everything on the buffer again
h
 
Old 11-05-2006, 04:05 PM   #7
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Yes, of course! I momentarily toyed with mentioning sed but couldn't remember how to do it offhand (and was too lazy to RTFM). That's nice, keefaz, much better than arsing around with a shell array.
 
Old 11-05-2006, 04:27 PM   #8
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by keefaz
Or use sed, example given with "info sed" :
Code:
#!/usr/bin/sed -nf
    
# reverse all lines of input, i.e. first line became last, ...
     
# from the second line, the buffer (which contains all previous lines)
# is *appended* to current line, so, the order will be reversed
1! G
     
# on the last line we're done -- print everything
$ p
     
# store everything on the buffer again
h
I saved the above as a executable file named "sed_reverse" under ~/bin and called it like so:

Quote:
cat du1.txt | sed_reverse
And I got this error:

Quote:
bash: /home/ubuntu/bin/sed_reverse: /usr/bin/sed: bad interpreter: No such file or directory
I think it would be easier just to have a regular sed command inside my script. Could I do that instead?
 
Old 11-05-2006, 04:37 PM   #9
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Maybe your sed is in /bin or /usr/local/bin? The "hash-bang" line must specify the correct path, the kernel doesn't search for the command. But yes, you could just call sed from the script, i.e.

Code:
#!/bin/sh
exec sed -nf ...
(The exec is optional, but prevents having a shell hanging around just waiting for sed to exit.)

One last point, redirection is a little more efficient than cat, e.g.

Code:
sed_reverse < du1.txt
(Though I realise it was just an example, you could of course, avoid the tmp file and pipe the output of du straight to the script.)
 
Old 11-05-2006, 04:42 PM   #10
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
There's also tac (cat backwards).
 
Old 11-05-2006, 04:44 PM   #11
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by soggycornflake
Maybe your sed is in /bin or /usr/local/bin? The "hash-bang" line must specify the correct path, the kernel doesn't search for the command. But yes, you could just call sed from the script, i.e.

Code:
#!/bin/sh
exec sed -nf ...
(The exec is optional, but prevents having a shell hanging around just waiting for sed to exit.)

One last point, redirection is a little more efficient than cat, e.g.

Code:
sed_reverse < du1.txt
(Though I realise it was just an example, you could of course, avoid the tmp file and pipe the output of du straight to the script.)
When I pipe the output of du to
Code:
sed -nf 1! G p h
I get this error:
Quote:
sed: couldn't open file 1!: No such file or directory
 
Old 11-05-2006, 04:46 PM   #12
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Quote:
There's also tac (cat backwards).
Damn, I'd completely forgotten about tac. Y'know, they should really supply manuals for these things. Maybe in a paginated format.

Quote:

When I pipe the output of du to
Code:

sed -nf 1! G p h

I get this error:
Quote:
sed: couldn't open file 1!: No such file or directory
Oops, forgot to check the options, you need to get rid of the -f and quote the sed 'script', and separate the commands with ; or newlines, e.g.

Code:
#!/bin/sh
sed -n '1!;G;$p;h;' $1
That should work now. But, I think osor has hit on the optimal solution.

Last edited by soggycornflake; 11-05-2006 at 04:53 PM.
 
Old 11-05-2006, 05:08 PM   #13
fatsheep
Member
 
Registered: Sep 2006
Posts: 79

Original Poster
Rep: Reputation: 15
Quote:
Originally Posted by soggycornflake
Damn, I'd completely forgotten about tac. Y'know, they should really supply manuals for these things. Maybe in a paginated format.



Oops, forgot to check the options, you need to get rid of the -f and quote the sed 'script', and separate the commands with ; or newlines, e.g.

Code:
#!/bin/sh
sed -n '1!;G;$p;h;' $1
That should work now. But, I think osor has hit on the optimal solution.
Yea I think I'll just use tac. I missed that post... Thanks guys.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Question about the -> or < function, as seen in this example... RHLinuxGUY Programming 12 04-10-2006 09:04 AM
A question about the listen function Nerox Programming 3 07-31-2005 09:06 PM
python call function in same file(very newbie question) rmanocha Programming 2 11-21-2004 12:04 AM
no mouse function? (still quite newbie) divingduck Linux - Distributions 8 04-25-2004 03:14 PM
A question about the gets() function in C OrganicX Programming 3 10-20-2003 01:11 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 08:53 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration