LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 02-02-2013, 11:03 AM   #1
lbrenner63
LQ Newbie
 
Registered: Feb 2013
Posts: 3

Rep: Reputation: Disabled
Smile Sorting question


My assignment this week for Linux is to create a file

I have everything working except the sorting - I can find nothing about sorting the list of names entered at the command prompt to the screen in sort order. I have tried adding the sort command every where in ths script. Any help would be very much appreciated. So at my command I would type ./linda.sh ken linda sam and nat I would want them to come out

Ken
Linda
Nat
Sm
__________________________________
#!/bin/bash
if [ $# -eq 4 ]
then
echo "you have entered the following $# names:"
echo "$*"

else [ $# -nt 4 ]
echo "You Fool! You must enter four names when invoking this script"
echo "Have some coffee and try again!"

fi
 
Old 02-02-2013, 11:27 AM   #2
etech3
Senior Member
 
Registered: Jul 2009
Location: Virginia
Distribution: Debian Stable Testing Sid Slackware CentOS
Posts: 1,055
Blog Entries: 2

Rep: Reputation: 45
You did try google right?

Code:
sort --help
Code:
man sort
 
Old 02-02-2013, 11:38 AM   #3
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
I would not guess that the OP's problem is with sort, nor that the man page of sort would help answer the problem.

The man page of sort includes info on how to get the input from a file and the option to instead get input from stdin.

But the OP has the input for sort in the command args of the script. Not in a file nor in stdin. So far as I understand, sort cannot take its input directly as command arguments (correct me if I'm wrong. I'm not an expert in this).

Obviously, any skilled bash user knows multiple ways to get contents from $* to (one per line in) either a file or a program's stdin. But I expect that is what the OP hasn't figured out.

Last edited by johnsfine; 02-02-2013 at 12:26 PM.
 
Old 02-02-2013, 12:00 PM   #4
shivaa
Senior Member
 
Registered: Jul 2012
Location: Grenoble, Fr.
Distribution: Sun Solaris, RHEL, Ubuntu, Debian 6.0
Posts: 1,800
Blog Entries: 4

Rep: Reputation: 286Reputation: 286Reputation: 286
In addition to sort, you can use:
Code:
~$ uniq -u infile
OR
~$ cat infile | uniq -u
 
Old 02-02-2013, 02:33 PM   #5
lbrenner63
LQ Newbie
 
Registered: Feb 2013
Posts: 3

Original Poster
Rep: Reputation: Disabled
Yes I have performed the sort --help
I don't need to sort a file so I don't need any options, right? I just want it alphabetically.

Syntax
sort [options] [file...]
sort --help
sort --version
As John says above I don't need to sort the file the ouput on the screen. My instructor shows an example of it so I know it works.

His out put looks like this

You have entered the following 4 names: sam roger linda ken

The list of the sorted names is:

linda
ken
roger
sam
 
Old 02-02-2013, 02:40 PM   #6
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 3,434

Rep: Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506
Hint: What does this do, and how might you use it?
Code:
echo $* | tr ' '  '\n'
 
Old 02-02-2013, 03:15 PM   #7
lbrenner63
LQ Newbie
 
Registered: Feb 2013
Posts: 3

Original Poster
Rep: Reputation: Disabled
Smile Thank you -- this has been solved

This sorted the name and put them on a separate line

Using the echo $* | tr ' ' '\n' | sort

[student@bsit_rh61 ~]$ ./week4.sh ken linda sam nat
you have entered the following 4 names:
ken
linda
sam
nat
the sorted list of names is:
ken
linda
nat
sam
[student@bsit_rh61 ~]$
 
Old 02-02-2013, 09:53 PM   #8
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Arch
Posts: 3,136

Rep: Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336
Bonus: handle names with spaces in them (hint: what's the difference between $* and $@).
 
Old 02-02-2013, 11:01 PM   #9
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 3,434

Rep: Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506
Quote:
Originally Posted by ntubski View Post
Bonus: handle names with spaces in them (hint: what's the difference between $* and $@).
That suggested pipeline has a bigger problem than that with embedded spaces, so there's little point in worrying about "$@".
 
Old 02-03-2013, 07:26 AM   #10
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by ntubski View Post
Bonus: handle names with spaces in them
How about :

Code:
 ( IFS="$(printf '\n ')"; echo "$*" ) | sort
The redefinition of IFS causes the expansion of $* to have \n between items rather than blank.

The ( ) around the two commands causes the redefinition of IFS to be discarded at the end of that scope (keeping the original definition).

The quote marks around $* are needed to keep echo from parsing its input (which would lose the new lines).

I tested with:

Code:
jfine:~> set 'Never call me "Johnny"' "I'm not a bash expert" QED First
jfine:~> echo "$*" | sort
Never call me "Johnny" I'm not a bash expert QED First
jfine:~> ( IFS="$(printf '\n ')" ; echo "$*" ) | sort
First
I'm not a bash expert
Never call me "Johnny"
QED
Quote:
Originally Posted by ntubski View Post
(hint: what's the difference between $* and $@).
I'm very much a beginner at bash, despite years of Linux experience. I didn't know the difference between $* and $@, so I looked it up. It doesn't seem to be a good path toward solving the problem. (I think that is what the above reply from rknichols was commenting on).

But I also had no clue IFS even existed, but looking up the difference between $* and $@ told me about IFS. Then google for an example of modifying IFS gave me the printf syntax (to get the \n into a redefined IFS).

So I don't think I used your hint, but I didn't have an answer until I looked into your hint.

Most of what I have learned about Linux over the years has come from my attempts to answer a question someone asked at LQ. I hope the OP was able to learn as much from this question as I was.

Last edited by johnsfine; 02-03-2013 at 08:52 AM.
 
Old 02-03-2013, 11:50 AM   #11
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Arch
Posts: 3,136

Rep: Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336
Quote:
Originally Posted by johnsfine View Post
Code:
 ( IFS="$(printf '\n ')"; echo "$*" ) | sort
That works, I would define IFS with a literal though:
Code:
 ( IFS='
'; echo "$*" ) | sort
# or bash-specific
( IFS=$'\n'; echo "$*" ) | sort
Quote:
The quote marks around $* are needed to keep echo from parsing its input (which would lose the new lines).
Slight nitpick: the args are parsed by the shell first and then passed to echo (which prints its args space-separated).

Quote:
I'm very much a beginner at bash, despite years of Linux experience. I didn't know the difference between $* and $@, so I looked it up. It doesn't seem to be a good path toward solving the problem. (I think that is what the above reply from rknichols was commenting on).
Well, I was thinking of a different method (I guess I should have mentioned looping in my hint as well):
Code:
# "$@" avoids re-splitting, so we can loop over the args 
for name in "$@" ; do
   printf '%s\n' "$name"
done | sort

# printf will actually loop over it's arguments so we can also do
printf '%s\n' "$@" | sort

# with GNU sort we can even handle names with newlines in them:
printf '%s\0' "$@" | sort -z
 
1 members found this post helpful.
Old 02-03-2013, 01:16 PM   #12
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 3,434

Rep: Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506Reputation: 1506
Now, to get names like "van Helsing" to sort properly ... .
 
Old 02-03-2013, 02:12 PM   #13
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by ntubski View Post
That works, I would define IFS with a literal though:
Code:
 ( IFS=$'\n'; echo "$*" ) | sort
Thanks. I did not know the syntax for including \n in a literal. So I tried IFS='\n', which doesn't work and then did a google search.

I found lots of examples using the printf syntax I showed. I guess the authors of those examples also didn't know the simpler way.

Quote:
Well, I was thinking of a different method (I guess I should have mentioned looping in my hint as well):
Yes, I assumed you intended a loop instead of the use of tr. I just thought (from the man page description of $@) there would be more problems with the special characters. I just tried your version with the rather nasty example from my previous post, and it works and I don't really understand why it doesn't trip over any of the special characters.

I think my version makes newline the only special character. But apparently you can do even better than that.

I didn't really know how to use a loop instead of tr. I knew it could work. I knew I could look it up. I thought it would be harder than what you just posted. (I didn't think the $@ hint would tell a beginner to figure out how to use a loop). I still prefer the LFS way and thanks again for showing me that way was also simpler than I thought.
Quote:
printf '%s\0' "$@" | sort -z
That doesn't quite work. Sorts right, but displays wrong.
Maybe you meant
Code:
printf '%s\n\0' "$@" | sort -z
With the even nastier input:
Code:
 set $'Never call me\n   "Johnny"' "I'm not a bash expert" QED First
My version messes up on the extra newline, displaying
Code:
   "Johnny"
First
I'm not a bash expert
Never call me
QED
But your version (plus the extra \n) works.

I'm impressed, but I think supporting an embedded \n in a name is a major step sillier than supporting blanks and special characters.

Quote:
Originally Posted by ntubski View Post
Slight nitpick: the args are parsed by the shell first and then passed to echo (which prints its args space-separated).
Right. I have worked on C startup code in too many non standard environments in which the startup code in each program parses the command line to create argc and argv (before calling main). I forgot that is supposed to be the job of the parent code before exec'ing the program.

Last edited by johnsfine; 02-03-2013 at 02:53 PM.
 
Old 02-03-2013, 03:41 PM   #14
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Arch
Posts: 3,136

Rep: Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336Reputation: 1336
Quote:
Originally Posted by johnsfine View Post
Yes, I assumed you intended a loop instead of the use of tr. I just thought (from the man page description of $@) there would be more problems with the special characters. I just tried your version with the rather nasty example from my previous post, and it works and I don't really understand why it doesn't trip over any of the special characters.
The way shell expansion works is pretty complicated (too complicated), there are 7 steps and the order should probably be described with a big state diagram (unfortunately, the manual does not include such a diagram). I guess the part you missed is that parameter expansion and quote removal are not performed on the result of parameter expansion, so having double quotes as part of a parameter's value has no effect.

Quote:
That doesn't quite work. Sorts right, but displays wrong.
Maybe you meant
Code:
printf '%s\n\0' "$@" | sort -z
Uh right, I left the nuls in the output, probably
Code:
printf '%s\0' "$@" | sort -z | tr '\0' '\n'
would be reasonable, although there isn't really any "right way" to display the result as plain text.


Quote:
Right. I have worked on C startup code in too many non standard environments in which the startup code in each program parses the command line to create argc and argv (before calling main).
Windows works like that. Coupled with the fact that cmd.exe does some parsing (including quote parsing) but still leaves quoting and argument parsing to the called program, trying to pass arguments with special characters in them is really a pain.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 sorting and linked lists Blackened Justice Programming 4 12-15-2011 07:53 PM
C programming sorting question himitsu Programming 1 08-19-2009 10:12 PM
Sorting Question D-KNUCKLES Linux - General 4 02-16-2007 01:40 PM
MySQL question on sorting (should be simple) BrianK Programming 3 08-09-2006 09:20 PM
Sorting question AMMullan Linux - General 12 01-19-2004 03:09 PM


All times are GMT -5. The time now is 12:05 PM.

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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration