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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
03-07-2012, 02:12 PM
|
#1
|
|
Member
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 777
Rep: 
|
Select lines based on key match
I want select lines from a large file based on matching a key value in a smaller file. The key values in the small file are unique; the matching values in the large file are not unique. Both files are sorted.
Sample small file ...
Sample large file ...
Code:
Bergeron Denise
Bergeron Terrence
Cole Carlton
Cole Donald
Cole Martha
Davis Michelle
Davis Joel
High Alice
High Robert
Phillips Edgar
Phillips Suzanne
Sample output file ...
Code:
Cole Carlton
Cole Donald
Cole Martha
Phillips Edgar
Phillips Suzanne
These samples are representative but the actual files are large so performance is a consideration.
Daniel B. Martin
|
|
|
|
03-07-2012, 02:23 PM
|
#2
|
|
Senior Member
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Debian, FreeBSD, Ubuntu (desktop)
Posts: 3,859
Rep: 
|
grep(1) can read patterns from a file, a la:
Code:
$ grep -f keys.txt people.txt
Last edited by anomie; 03-07-2012 at 02:26 PM.
|
|
|
1 members found this post helpful.
|
03-07-2012, 03:41 PM
|
#3
|
|
Member
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 777
Original Poster
Rep: 
|
Quote:
Originally Posted by anomie
Code:
$ grep -f keys.txt people.txt
|
Thank you, anomie, we are on the right track. It is necessary to match the key strings to the left-most blank-delimited field only. That will make the grep run faster and, more importantly, avoid false matches. If the keys file contains "Martin" I don't want matches on lines in the people file such as "Davidson Martin."
How may we limit the scope of the grep?
Daniel B. Martin
|
|
|
|
03-07-2012, 03:54 PM
|
#4
|
|
Senior Member
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Debian, FreeBSD, Ubuntu (desktop)
Posts: 3,859
Rep: 
|
There may be a more efficient means for solving this, but I'd simply put the patterns in the keys.txt file.
Input files:
Code:
$ cat keys.txt
^Cole\>
^Phillips\>
Code:
$ cat people.txt
Bergeron Denise
Bergeron Terrence
Cole Carlton
Cole Donald
Cole Martha
Davis Michelle
Davis Joel
High Alice
High Robert
Phillips Edgar
Phillips Suzanne
Jo Cole
Coleen Hsu
Result from grep(1):
Code:
$ grep -f keys.txt people.txt
Cole Carlton
Cole Donald
Cole Martha
Phillips Edgar
Phillips Suzanne
|
|
|
1 members found this post helpful.
|
03-07-2012, 05:02 PM
|
#5
|
|
Senior Member
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
|
How about
Code:
awk -v 'keyfile=path/to/small/file' 'BEGIN {
while ((getline < keyfile) > 0) key[$1]
close(keyfile)
}
($1 in key)' 'path/to/large/file'
The BEGIN rule reads the key file first. First field (word) on each line is saved to the key array as a key, with a null value. (In awk, just referencing an array member will create it. Assume there is a = NULL at the end of the second line.)
The actual rule on the last line reads: If first field matches a key in key array, then print the record. (You can omit the implicit { print } for the last rule.)
Essentially, the above reads the first fields in the small file, then outputs the records (lines) of the large file only if the first field matches one of the ones read from the small file.
|
|
|
|
03-08-2012, 06:40 AM
|
#6
|
|
Senior Member
Registered: Dec 2004
Location: Marburg, Germany
Distribution: openSUSE 11.4
Posts: 1,314
|
Code:
$ join keys.txt people.txt
By default it will match on the first column.
Last edited by Reuti; 03-08-2012 at 06:41 AM.
Reason: Changed file names
|
|
|
|
03-08-2012, 10:52 AM
|
#7
|
|
Member
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 777
Original Poster
Rep: 
|
Quote:
Originally Posted by anomie
There may be a more efficient means for solving this, but I'd simply put the patterns in the keys.txt file.
|
Code:
$ cat keys.txt
^Cole\>
^Phillips\>
The ^ means "starting in column 1" as desired. I don't understand what the \> does for us. I tried this method using only the ^ prefix and it seemed to work.
Daniel B. Martin
|
|
|
|
03-08-2012, 11:11 AM
|
#8
|
|
Senior Member
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Debian, FreeBSD, Ubuntu (desktop)
Posts: 3,859
Rep: 
|
Those are regular expressions (anchors). The meanings are: - ^ -- match beginning of line
- \> -- match end of word
If you do not use the latter, you'll also match names like "Coleman Butler".
Last edited by anomie; 03-08-2012 at 11:12 AM.
|
|
|
1 members found this post helpful.
|
03-08-2012, 06:13 PM
|
#9
|
|
Member
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 777
Original Poster
Rep: 
|
Quote:
Originally Posted by anomie
[*] \> -- match end of word[*]
|
Thank you, this is something I haven't seen before.
I try to learn from tutorials and Google searches. Even knowing \> I found no mention of it anywhere. Help me to help myself -- where could I have found this on my own?
Daniel B. Martin
|
|
|
|
03-08-2012, 08:26 PM
|
#10
|
|
Senior Member
Registered: Nov 2004
Location: Texas
Distribution: RHEL, Debian, FreeBSD, Ubuntu (desktop)
Posts: 3,859
Rep: 
|
In this case, you can view the manpages for grep(1):
Code:
Anchoring
The caret ^ and the dollar sign $ are meta-characters that respectively
match the empty string at the beginning and end of a line.
The Backslash Character and Special Expressions
The symbols \< and \> respectively match the empty string at the
beginning and end of a word...
Last edited by anomie; 03-08-2012 at 08:31 PM.
Reason: changed to manpage.
|
|
|
1 members found this post helpful.
|
03-09-2012, 11:03 AM
|
#11
|
|
Member
Registered: Apr 2010
Location: Apex, NC, USA
Distribution: Ubuntu
Posts: 777
Original Poster
Rep: 
|
Quote:
Originally Posted by anomie
In this case, you can view the manpages for grep(1) ...
|
Yes, found it, thank you. As I climb the Linux learning curve, it becomes apparent that mastering grep and sed requires a proficiency in writing Regular Expressions.
Daniel B. Martin
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 12:27 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|